mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-15 08:26:04 +08:00
Apply the rule of zero for etl::optional type.
Correct move behavior of `TestDataM` - it should preserve `valid` value. Implemented overloads of `etl::make_optional` free function. Extend optional moveable tests - fundamental vs non-fundamental - move construct/assign from valueless - Verify nothrow of `etl::swap` for `etl::optional`.
This commit is contained in:
parent
b9b36d8155
commit
e36b08cff5
@ -142,11 +142,12 @@ namespace etl
|
||||
}
|
||||
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
|
||||
//***************************************************************************
|
||||
/// Copy constructor.
|
||||
//***************************************************************************
|
||||
ETL_CONSTEXPR20_STL
|
||||
optional_impl(const optional_impl<T>& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
|
||||
optional_impl(const optional_impl& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
|
||||
{
|
||||
if (other.has_value())
|
||||
{
|
||||
@ -160,7 +161,7 @@ namespace etl
|
||||
/// Move constructor.
|
||||
//***************************************************************************
|
||||
ETL_CONSTEXPR20_STL
|
||||
optional_impl(optional_impl<T>&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value)
|
||||
optional_impl(optional_impl&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value)
|
||||
{
|
||||
if (other.has_value())
|
||||
{
|
||||
@ -231,7 +232,7 @@ namespace etl
|
||||
/// Assignment operator from optional_impl.
|
||||
//***************************************************************************
|
||||
ETL_CONSTEXPR20_STL
|
||||
optional_impl& operator=(const optional_impl<T>& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
|
||||
optional_impl& operator=(const optional_impl& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
@ -478,11 +479,11 @@ namespace etl
|
||||
/// Swaps this value with another.
|
||||
//***************************************************************************
|
||||
ETL_CONSTEXPR20_STL
|
||||
void swap(optional_impl& other)
|
||||
void swap(optional_impl& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value)
|
||||
{
|
||||
optional_impl temp(*this);
|
||||
*this = other;
|
||||
other = temp;
|
||||
optional_impl temp(ETL_MOVE(*this));
|
||||
*this = ETL_MOVE(other);
|
||||
other = ETL_MOVE(temp);
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
@ -498,7 +499,7 @@ namespace etl
|
||||
///
|
||||
//*************************************************************************
|
||||
ETL_CONSTEXPR20_STL
|
||||
T& emplace(const optional_impl<T>& other)
|
||||
T& emplace(const optional_impl& other)
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(other.has_value(), ETL_ERROR(optional_invalid));
|
||||
@ -750,10 +751,11 @@ namespace etl
|
||||
}
|
||||
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
|
||||
//***************************************************************************
|
||||
/// Copy constructor.
|
||||
//***************************************************************************
|
||||
ETL_CONSTEXPR14 optional_impl(const optional_impl<T>& other) ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 optional_impl(const optional_impl& other) ETL_NOEXCEPT
|
||||
{
|
||||
if (other.has_value())
|
||||
{
|
||||
@ -827,7 +829,7 @@ namespace etl
|
||||
//***************************************************************************
|
||||
/// Assignment operator from optional_impl.
|
||||
//***************************************************************************
|
||||
ETL_CONSTEXPR14 optional_impl& operator=(const optional_impl<T>& other) ETL_NOEXCEPT
|
||||
ETL_CONSTEXPR14 optional_impl& operator=(const optional_impl& other) ETL_NOEXCEPT
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
@ -1078,7 +1080,7 @@ namespace etl
|
||||
///
|
||||
//*************************************************************************
|
||||
ETL_CONSTEXPR20_STL
|
||||
T& emplace(const optional_impl<T>& other)
|
||||
T& emplace(const optional_impl& other)
|
||||
{
|
||||
#if ETL_IS_DEBUG_BUILD
|
||||
ETL_ASSERT(other.has_value(), ETL_ERROR(optional_invalid));
|
||||
@ -1336,24 +1338,8 @@ namespace etl
|
||||
#endif
|
||||
|
||||
#include "private/diagnostic_uninitialized_push.h"
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Copy constructor.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
ETL_CONSTEXPR14 optional(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
|
||||
: impl_t(other)
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Copy constructor.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
ETL_CONSTEXPR20_STL optional(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
|
||||
: impl_t(other)
|
||||
{
|
||||
}
|
||||
#if ETL_USING_CPP11
|
||||
#else
|
||||
//***************************************************************************
|
||||
/// Copy constructor.
|
||||
@ -1365,26 +1351,6 @@ namespace etl
|
||||
#endif
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Move constructor.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
ETL_CONSTEXPR14 optional(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value)
|
||||
: impl_t(etl::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Move constructor.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
ETL_CONSTEXPR20_STL optional(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value)
|
||||
: impl_t(etl::move(other))
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Converting constructor from value type.
|
||||
@ -1502,27 +1468,6 @@ namespace etl
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Assignment operator from optional.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
ETL_CONSTEXPR14 optional& operator=(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
|
||||
{
|
||||
impl_t::operator=(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Assignment operator from optional.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
ETL_CONSTEXPR20_STL optional& operator=(const optional& other) ETL_NOEXCEPT_IF(etl::is_nothrow_copy_constructible<T>::value)
|
||||
{
|
||||
impl_t::operator=(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
//***************************************************************************
|
||||
/// Assignment operator from optional.
|
||||
@ -1535,30 +1480,6 @@ namespace etl
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Move assignment operator from optional.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
ETL_CONSTEXPR14 optional& operator=(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value)
|
||||
{
|
||||
impl_t::operator=(etl::move(other));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Move assignment operator from optional.
|
||||
//***************************************************************************
|
||||
template <typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
ETL_CONSTEXPR20_STL optional& operator=(optional&& other) ETL_NOEXCEPT_IF(etl::is_nothrow_move_constructible<T>::value)
|
||||
{
|
||||
impl_t::operator=(etl::move(other));
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//***************************************************************************
|
||||
/// Converting assignment operator from value type.
|
||||
@ -2226,6 +2147,71 @@ namespace etl
|
||||
|
||||
#include "private/diagnostic_pop.h"
|
||||
|
||||
#if ETL_CPP11_SUPPORTED
|
||||
//***************************************************************************
|
||||
/// Creates an optional object from `value`.
|
||||
//***************************************************************************
|
||||
template <typename T, typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
ETL_CONSTEXPR14 etl::optional<typename etl::decay<T>::type> make_optional(T&& value) //
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, T&&>::value))
|
||||
{
|
||||
return etl::optional<typename etl::decay<T>::type>(etl::forward<T>(value));
|
||||
}
|
||||
template <typename T, typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
ETL_CONSTEXPR20_STL etl::optional<typename etl::decay<T>::type> make_optional(T&& value) //
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, T&&>::value))
|
||||
{
|
||||
return etl::optional<typename etl::decay<T>::type>(etl::forward<T>(value));
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Creates an optional object constructed in-place from `args...` .
|
||||
/// Equivalent to `return etl::optional<T>(etl::in_place, etl::forward<Args>(args)...);`.
|
||||
/// This overload participates in overload resolution only if
|
||||
/// `etl::is_constructible_v<T, Args...>` is true.
|
||||
//***************************************************************************
|
||||
template <typename T, typename... Args, //
|
||||
typename etl::enable_if< etl::is_constructible<T, Args...>::value, int>::type = 0, //
|
||||
typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
ETL_CONSTEXPR14 etl::optional<T> make_optional(Args&&... args) //
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, Args...>::value))
|
||||
{
|
||||
return etl::optional<typename etl::decay<T>::type>(etl::in_place_t{}, etl::forward<Args>(args)...);
|
||||
}
|
||||
template <typename T, typename... Args, //
|
||||
typename etl::enable_if< etl::is_constructible<T, Args...>::value, int>::type = 0, //
|
||||
typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
ETL_CONSTEXPR20_STL etl::optional<T> make_optional(Args&&... args) //
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, Args...>::value))
|
||||
{
|
||||
return etl::optional<typename etl::decay<T>::type>(etl::in_place_t{}, etl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#if ETL_HAS_INITIALIZER_LIST
|
||||
//***************************************************************************
|
||||
/// Creates an optional object constructed in-place from `ilist` and `args...`.
|
||||
/// Equivalent to `return etl::optional<T>(std::in_place, ilist, std::forward<Args>(args)...);`.
|
||||
/// This overload participates in overload resolution only if
|
||||
/// `etl::is_constructible_v<T, std::initializer_list<U>&, Args...>` is true.
|
||||
//***************************************************************************
|
||||
template <typename T, typename TL, typename... Args, //
|
||||
typename etl::enable_if< etl::is_constructible<T, std::initializer_list<TL>&, Args...>::value, int>::type = 0, //
|
||||
typename U = T, ETL_OPTIONAL_ENABLE_CPP14>
|
||||
ETL_CONSTEXPR14 etl::optional<T> make_optional(std::initializer_list<TL> ilist, Args&&... args)
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, std::initializer_list<TL>&, Args...>::value))
|
||||
{
|
||||
return etl::optional<typename etl::decay<T>::type>(etl::in_place_t{}, ilist, etl::forward<Args>(args)...);
|
||||
}
|
||||
template <typename T, typename TL, typename... Args, //
|
||||
typename etl::enable_if< etl::is_constructible<T, std::initializer_list<TL>&, Args...>::value, int>::type = 0, //
|
||||
typename U = T, ETL_OPTIONAL_ENABLE_CPP20_STL>
|
||||
ETL_CONSTEXPR20_STL etl::optional<T> make_optional(std::initializer_list<TL> ilist, Args&&... args)
|
||||
ETL_NOEXCEPT_IF((etl::is_nothrow_constructible<T, std::initializer_list<TL>&, Args...>::value))
|
||||
{
|
||||
return etl::optional<typename etl::decay<T>::type>(etl::in_place_t{}, ilist, etl::forward<Args>(args)...);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
//***************************************************************************
|
||||
/// Make an optional.
|
||||
//***************************************************************************
|
||||
@ -2234,6 +2220,7 @@ namespace etl
|
||||
{
|
||||
return etl::optional<typename etl::decay<T>::type>(value);
|
||||
}
|
||||
#endif
|
||||
|
||||
//***************************************************************************
|
||||
/// Template deduction guides.
|
||||
@ -2242,16 +2229,17 @@ namespace etl
|
||||
template <typename T>
|
||||
optional(T) -> optional<T>;
|
||||
#endif
|
||||
} // namespace etl
|
||||
|
||||
//*************************************************************************
|
||||
/// Swaps the values.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR20_STL void swap(etl::optional<T>& lhs, etl::optional<T>& rhs)
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
//*************************************************************************
|
||||
/// Swaps the values.
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR20_STL void swap(etl::optional<T>& lhs, etl::optional<T>& rhs) ETL_NOEXCEPT_FROM(lhs.swap(rhs))
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
} // namespace etl
|
||||
|
||||
#undef ETL_OPTIONAL_ENABLE_CPP14
|
||||
#undef ETL_OPTIONAL_ENABLE_CPP20_STL
|
||||
|
||||
13
test/data.h
13
test/data.h
@ -201,14 +201,14 @@ public:
|
||||
|
||||
TestDataM(TestDataM&& other) noexcept
|
||||
: value(std::move(other.value))
|
||||
, valid(true)
|
||||
, valid(other.valid)
|
||||
{
|
||||
other.valid = false;
|
||||
}
|
||||
|
||||
TestDataM(const TestDataM&& other) noexcept
|
||||
: value(std::move(other.value))
|
||||
, valid(true)
|
||||
, valid(other.valid)
|
||||
{
|
||||
other.valid = false;
|
||||
}
|
||||
@ -220,10 +220,13 @@ public:
|
||||
|
||||
TestDataM& operator=(TestDataM&& other) noexcept
|
||||
{
|
||||
value = std::move(other.value);
|
||||
valid = true;
|
||||
if (this != &other)
|
||||
{
|
||||
value = std::move(other.value);
|
||||
valid = other.valid;
|
||||
|
||||
other.valid = false;
|
||||
other.valid = false;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -28,13 +28,15 @@ SOFTWARE.
|
||||
|
||||
#include "unit_test_framework.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "data.h"
|
||||
#include "etl/algorithm.h"
|
||||
#include "etl/optional.h"
|
||||
#include "etl/vector.h"
|
||||
|
||||
@ -83,6 +85,29 @@ namespace
|
||||
};
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
|
||||
struct TestIL
|
||||
{
|
||||
constexpr TestIL()
|
||||
: a(0)
|
||||
, b(0)
|
||||
, c(0)
|
||||
{
|
||||
}
|
||||
|
||||
ETL_CONSTEXPR20 TestIL(std::initializer_list<int> il, int a_, int b_, int c_)
|
||||
: a(a_)
|
||||
, b(b_)
|
||||
, c(c_)
|
||||
{
|
||||
etl::copy_n(il.begin(), std::min(il.size(), arr.size()), arr.begin());
|
||||
}
|
||||
|
||||
std::array<int, 3> arr{};
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
};
|
||||
|
||||
SUITE(test_optional)
|
||||
{
|
||||
//*************************************************************************
|
||||
@ -91,38 +116,38 @@ namespace
|
||||
etl::optional<Data> data1;
|
||||
etl::optional<Data> data2;
|
||||
|
||||
CHECK(!bool(data1));
|
||||
CHECK(!bool(data2));
|
||||
CHECK(!static_cast<bool>(data1));
|
||||
CHECK(!static_cast<bool>(data2));
|
||||
CHECK(!data1.has_value());
|
||||
CHECK(!data2.has_value());
|
||||
|
||||
data1 = Data("Hello");
|
||||
CHECK(bool(data1));
|
||||
CHECK(static_cast<bool>(data1));
|
||||
CHECK(data1.has_value());
|
||||
CHECK_EQUAL(Data("Hello"), data1);
|
||||
|
||||
data1 = data2;
|
||||
CHECK(!bool(data1));
|
||||
CHECK(!bool(data2));
|
||||
CHECK(!static_cast<bool>(data1));
|
||||
CHECK(!static_cast<bool>(data2));
|
||||
CHECK(!data1.has_value());
|
||||
CHECK(!data2.has_value());
|
||||
|
||||
data1 = Data("World");
|
||||
data2 = data1;
|
||||
CHECK(bool(data1));
|
||||
CHECK(bool(data2));
|
||||
CHECK(static_cast<bool>(data1));
|
||||
CHECK(static_cast<bool>(data2));
|
||||
CHECK(data1.has_value());
|
||||
CHECK(data2.has_value());
|
||||
|
||||
etl::optional<Data> data3(data1);
|
||||
CHECK(bool(data3));
|
||||
const etl::optional<Data> data3(data1);
|
||||
CHECK(static_cast<bool>(data3));
|
||||
CHECK(data3.has_value());
|
||||
CHECK_EQUAL(data1, data3);
|
||||
|
||||
etl::optional<Data> data4;
|
||||
data4 = Data("Hello");
|
||||
data4 = etl::nullopt;
|
||||
CHECK(!bool(data4));
|
||||
CHECK(!static_cast<bool>(data4));
|
||||
CHECK(!data4.has_value());
|
||||
}
|
||||
|
||||
@ -133,7 +158,7 @@ namespace
|
||||
constexpr etl::optional<int> opt(etl::in_place_t{}, 1);
|
||||
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK(bool(opt));
|
||||
CHECK(static_cast<bool>(opt));
|
||||
CHECK_EQUAL(1, opt.value());
|
||||
}
|
||||
#endif
|
||||
@ -157,7 +182,7 @@ namespace
|
||||
constexpr etl::optional<TestData> opt(etl::in_place_t{}, 1, 2);
|
||||
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK(bool(opt));
|
||||
CHECK(static_cast<bool>(opt));
|
||||
CHECK_EQUAL(1, opt.value().a);
|
||||
CHECK_EQUAL(2, opt.value().b);
|
||||
}
|
||||
@ -166,34 +191,14 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST(test_construct_from_initializer_list_and_arguments)
|
||||
{
|
||||
struct S
|
||||
{
|
||||
S()
|
||||
: vi()
|
||||
, a(0)
|
||||
, b(0)
|
||||
{
|
||||
}
|
||||
etl::optional<TestIL> opt(etl::in_place_t{}, {10, 11, 12}, 1, 2, 3);
|
||||
|
||||
S(std::initializer_list<int> il, int a_, int b_)
|
||||
: vi(il)
|
||||
, a(a_)
|
||||
, b(b_)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<int> vi;
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
etl::optional<S> opt(etl::in_place_t{}, {10, 11, 12}, 1, 2);
|
||||
|
||||
CHECK_EQUAL(10, opt.value().vi[0]);
|
||||
CHECK_EQUAL(11, opt.value().vi[1]);
|
||||
CHECK_EQUAL(12, opt.value().vi[2]);
|
||||
CHECK_EQUAL(10, opt.value().arr[0]);
|
||||
CHECK_EQUAL(11, opt.value().arr[1]);
|
||||
CHECK_EQUAL(12, opt.value().arr[2]);
|
||||
CHECK_EQUAL(1, opt.value().a);
|
||||
CHECK_EQUAL(2, opt.value().b);
|
||||
CHECK_EQUAL(3, opt.value().c);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -201,10 +206,10 @@ namespace
|
||||
{
|
||||
Data data("Hello");
|
||||
|
||||
etl::optional<Data> opt{data};
|
||||
const etl::optional<Data> opt{data};
|
||||
|
||||
CHECK(opt.has_value());
|
||||
CHECK(bool(opt));
|
||||
CHECK(static_cast<bool>(opt));
|
||||
CHECK_EQUAL(data, opt);
|
||||
}
|
||||
|
||||
@ -258,20 +263,89 @@ namespace
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_moveable)
|
||||
TEST(test_moveable_not_fundamental)
|
||||
{
|
||||
#include "etl/private/diagnostic_pessimizing_move_push.h"
|
||||
|
||||
// Construct by moving value.
|
||||
etl::optional<DataM> data(std::move(DataM(1)));
|
||||
CHECK(data.has_value());
|
||||
CHECK(data->valid);
|
||||
CHECK_EQUAL(1U, data.value().value);
|
||||
CHECK(bool(data));
|
||||
CHECK(static_cast<bool>(data));
|
||||
|
||||
data = std::move(etl::optional<DataM>(std::move(DataM(2))));
|
||||
CHECK_EQUAL(2U, data.value().value);
|
||||
CHECK(bool(data));
|
||||
// Assign by moving optional.
|
||||
{
|
||||
etl::optional<DataM> temp(DataM(2));
|
||||
data = std::move(temp);
|
||||
CHECK(temp.has_value() && !temp->valid); // NOLINT "Note that a moved-from optional still contains a value (although invalid one)."
|
||||
CHECK(data.has_value());
|
||||
CHECK(data->valid);
|
||||
CHECK(static_cast<bool>(data));
|
||||
CHECK_EQUAL(2U, data.value().value);
|
||||
}
|
||||
|
||||
etl::optional<DataM> data2(etl::move(data));
|
||||
CHECK_EQUAL(2U, data2.value().value);
|
||||
CHECK(bool(data2));
|
||||
// Construct by moving optional.
|
||||
{
|
||||
etl::optional<DataM> data2(etl::move(data));
|
||||
CHECK(data.has_value() && !data->valid); // NOLINT "Note that a moved-from optional still contains a value (although invalid one)."
|
||||
CHECK(data2.has_value());
|
||||
CHECK(data2->valid);
|
||||
CHECK(static_cast<bool>(data2));
|
||||
CHECK_EQUAL(2U, data2.value().value);
|
||||
}
|
||||
|
||||
// Try to move construct/assign from valueless.
|
||||
{
|
||||
etl::optional<DataM> temp;
|
||||
etl::optional<DataM> data2(etl::move(temp));
|
||||
CHECK(!data2.has_value());
|
||||
|
||||
data2 = etl::move(etl::optional<DataM>());
|
||||
CHECK(!data2.has_value());
|
||||
}
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_moveable_fundamental)
|
||||
{
|
||||
#include "etl/private/diagnostic_pessimizing_move_push.h"
|
||||
|
||||
// Construct by moving value.
|
||||
etl::optional<std::uint8_t> data(1U);
|
||||
CHECK(data.has_value());
|
||||
CHECK_EQUAL(1U, data.value());
|
||||
CHECK(static_cast<bool>(data));
|
||||
|
||||
// Assign by moving optional.
|
||||
{
|
||||
etl::optional<std::uint8_t> temp(2U);
|
||||
data = std::move(temp);
|
||||
CHECK(temp.has_value()); // NOLINT "Note that a moved-from optional still contains a value."
|
||||
CHECK(data.has_value());
|
||||
CHECK(static_cast<bool>(data));
|
||||
CHECK_EQUAL(2U, data.value());
|
||||
}
|
||||
|
||||
// Construct by moving optional.
|
||||
{
|
||||
etl::optional<std::uint8_t> data2(etl::move(data));
|
||||
CHECK(data.has_value()); // NOLINT "Note that a moved-from optional still contains a value."
|
||||
CHECK(data2.has_value());
|
||||
CHECK(static_cast<bool>(data2));
|
||||
CHECK_EQUAL(2U, data2.value());
|
||||
}
|
||||
|
||||
// Try to move construct/assign from valueless.
|
||||
{
|
||||
etl::optional<std::uint8_t> temp;
|
||||
etl::optional<std::uint8_t> data2(etl::move(temp));
|
||||
CHECK(!data2.has_value());
|
||||
|
||||
data2 = etl::move(etl::optional<std::uint8_t>());
|
||||
CHECK(!data2.has_value());
|
||||
}
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
}
|
||||
|
||||
@ -281,7 +355,7 @@ namespace
|
||||
etl::optional<int> data(etl::nullopt);
|
||||
data = 1;
|
||||
data = etl::nullopt;
|
||||
CHECK(!bool(data));
|
||||
CHECK(!static_cast<bool>(data));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -290,7 +364,7 @@ namespace
|
||||
etl::optional<Data> data(etl::nullopt);
|
||||
data = Data("Hello");
|
||||
data = etl::nullopt;
|
||||
CHECK(!bool(data));
|
||||
CHECK(!static_cast<bool>(data));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -317,7 +391,7 @@ namespace
|
||||
CHECK_EQUAL(5, resultFT);
|
||||
|
||||
const NonFundamentalType constNFT{"Default"};
|
||||
NonFundamentalType resultNFT = etl::optional<NonFundamentalType>{}.value_or(constNFT);
|
||||
const NonFundamentalType resultNFT = etl::optional<NonFundamentalType>{}.value_or(constNFT);
|
||||
CHECK_EQUAL("Default", resultNFT);
|
||||
}
|
||||
|
||||
@ -339,12 +413,12 @@ namespace
|
||||
|
||||
TEST(test_chained_value_or_github_bug_720)
|
||||
{
|
||||
github_bug_720_bug_helper helper{};
|
||||
const github_bug_720_bug_helper helper{};
|
||||
|
||||
int value1 = helper.get_valid().value_or(1);
|
||||
const int value1 = helper.get_valid().value_or(1);
|
||||
CHECK_EQUAL(5, value1);
|
||||
|
||||
int value2 = helper.get_invalid().value_or(1);
|
||||
const int value2 = helper.get_invalid().value_or(1);
|
||||
CHECK_EQUAL(1, value2);
|
||||
}
|
||||
|
||||
@ -783,11 +857,11 @@ namespace
|
||||
|
||||
container.resize(5, Data("1"));
|
||||
|
||||
CHECK(bool(container[0]));
|
||||
CHECK(bool(container[1]));
|
||||
CHECK(bool(container[2]));
|
||||
CHECK(bool(container[3]));
|
||||
CHECK(bool(container[4]));
|
||||
CHECK(static_cast<bool>(container[0]));
|
||||
CHECK(static_cast<bool>(container[1]));
|
||||
CHECK(static_cast<bool>(container[2]));
|
||||
CHECK(static_cast<bool>(container[3]));
|
||||
CHECK(static_cast<bool>(container[4]));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -796,10 +870,10 @@ namespace
|
||||
// The indexed access doesn't work in Linux for some reason!!!
|
||||
#ifndef ETL_PLATFORM_LINUX
|
||||
etl::optional<etl::vector<Data, 10>> container;
|
||||
CHECK(!bool(container)); //
|
||||
CHECK(!static_cast<bool>(container)); //
|
||||
|
||||
container = etl::vector<Data, 10>();
|
||||
CHECK(bool(container));
|
||||
CHECK(static_cast<bool>(container));
|
||||
|
||||
container.value().resize(5, Data("1"));
|
||||
CHECK_EQUAL(5U, container.value().size());
|
||||
@ -823,51 +897,61 @@ namespace
|
||||
//*************************************************************************
|
||||
TEST(test_swap)
|
||||
{
|
||||
etl::optional<Data> original1(Data("1"));
|
||||
etl::optional<Data> original2(Data("2"));
|
||||
const etl::optional<Data> original1(Data("1"));
|
||||
const etl::optional<Data> original2(Data("2"));
|
||||
|
||||
etl::optional<Data> data1;
|
||||
etl::optional<Data> data2;
|
||||
|
||||
// Both invalid.
|
||||
swap(data1, data2);
|
||||
CHECK(!bool(data1));
|
||||
CHECK(!bool(data2));
|
||||
CHECK(!static_cast<bool>(data1));
|
||||
CHECK(!static_cast<bool>(data2));
|
||||
|
||||
// Data1 valid;
|
||||
// data1 is valid
|
||||
data1 = original1;
|
||||
data2 = etl::nullopt;
|
||||
swap(data1, data2);
|
||||
CHECK(!bool(data1));
|
||||
CHECK(bool(data2));
|
||||
CHECK(!static_cast<bool>(data1));
|
||||
CHECK(static_cast<bool>(data2));
|
||||
CHECK_EQUAL(data2, original1);
|
||||
|
||||
// Data2 valid;
|
||||
// data2 is valid
|
||||
data1 = etl::nullopt;
|
||||
data2 = original2;
|
||||
swap(data1, data2);
|
||||
CHECK(bool(data1));
|
||||
CHECK(!bool(data2));
|
||||
CHECK(static_cast<bool>(data1));
|
||||
CHECK(!static_cast<bool>(data2));
|
||||
CHECK_EQUAL(data1, original2);
|
||||
|
||||
// Both valid;
|
||||
// both are valid
|
||||
data1 = original1;
|
||||
data2 = original2;
|
||||
swap(data1, data2);
|
||||
CHECK(bool(data1));
|
||||
CHECK(bool(data2));
|
||||
CHECK(static_cast<bool>(data1));
|
||||
CHECK(static_cast<bool>(data2));
|
||||
CHECK_EQUAL(data1, original2);
|
||||
CHECK_EQUAL(data2, original1);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_swap_moveable)
|
||||
{
|
||||
etl::optional<DataM> data1(1U);
|
||||
etl::optional<DataM> data2(2U);
|
||||
swap(data1, data2);
|
||||
CHECK_EQUAL(2U, data1.value().value);
|
||||
CHECK_EQUAL(1U, data2.value().value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_reset)
|
||||
{
|
||||
etl::optional<Data> data(Data("1"));
|
||||
CHECK(bool(data));
|
||||
CHECK(static_cast<bool>(data));
|
||||
|
||||
data.reset();
|
||||
CHECK(!bool(data));
|
||||
CHECK(!static_cast<bool>(data));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -908,10 +992,10 @@ namespace
|
||||
|
||||
TEST(test_optional_pod_emplace_bug_712)
|
||||
{
|
||||
etl::optional<MyPODObject> optionalObject; // The Test: Does this compile for an object with a
|
||||
// deleted default constructor?
|
||||
const etl::optional<MyPODObject> optionalObject; // The Test: Does this compile for an object with a
|
||||
// deleted default constructor?
|
||||
|
||||
// Make sure it isn't optimised away.
|
||||
// Make sure it isn't optimized away.
|
||||
CHECK_FALSE(optionalObject.has_value());
|
||||
}
|
||||
|
||||
@ -1080,10 +1164,10 @@ namespace
|
||||
|
||||
TEST(range_based_for_loop_with_value)
|
||||
{
|
||||
etl::optional<int> opt = 4;
|
||||
const etl::optional<int> opt = 4;
|
||||
|
||||
int sum = 0;
|
||||
for (int value : opt)
|
||||
for (const int value : opt)
|
||||
{
|
||||
sum += value;
|
||||
}
|
||||
@ -1093,10 +1177,10 @@ namespace
|
||||
|
||||
TEST(range_based_for_loop_empty)
|
||||
{
|
||||
etl::optional<int> opt;
|
||||
const etl::optional<int> opt;
|
||||
|
||||
int sum = 0;
|
||||
for (int value : opt)
|
||||
for (const int value : opt)
|
||||
{
|
||||
sum += value;
|
||||
}
|
||||
@ -1106,8 +1190,8 @@ namespace
|
||||
|
||||
TEST(test_range_based_for_loop_non_trivial)
|
||||
{
|
||||
etl::optional<Data> opt = Data("TEST");
|
||||
int count = 0;
|
||||
const etl::optional<Data> opt = Data("TEST");
|
||||
int count = 0;
|
||||
|
||||
for (const Data& value : opt)
|
||||
{
|
||||
@ -1163,8 +1247,8 @@ namespace
|
||||
{
|
||||
// etl::optional<T> should compile when T has deleted copy/move
|
||||
// constructors, as long as T is constructible from the given arguments.
|
||||
Issue146_Container with_value(42);
|
||||
Issue146_Container without_value;
|
||||
const Issue146_Container with_value(42);
|
||||
const Issue146_Container without_value;
|
||||
|
||||
CHECK_TRUE(with_value.a.has_value());
|
||||
CHECK_EQUAL(42, with_value.a->_some);
|
||||
@ -1172,12 +1256,103 @@ namespace
|
||||
CHECK_FALSE(without_value.a.has_value());
|
||||
|
||||
// in_place construction should also work
|
||||
etl::optional<Issue146_NonCopyable> opt(etl::in_place_t{}, 99);
|
||||
const etl::optional<Issue146_NonCopyable> opt(etl::in_place_t{}, 99);
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK_EQUAL(99, opt->_some);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(test_make_optional_1_lvalue)
|
||||
{
|
||||
const std::string test_value("TEST");
|
||||
Data test_data(test_value);
|
||||
const etl::optional<Data> opt = etl::make_optional(test_data);
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK_EQUAL(test_value, opt.value().value);
|
||||
}
|
||||
|
||||
TEST(test_make_optional_1_const_value)
|
||||
{
|
||||
const std::string test_value("TEST");
|
||||
const Data test_data(test_value);
|
||||
const etl::optional<Data> opt = etl::make_optional(test_data);
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK_EQUAL(test_data.value, opt.value().value);
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
TEST(test_make_optional_1_rvalue)
|
||||
{
|
||||
constexpr uint32_t test_value = 42;
|
||||
DataM test_data(test_value);
|
||||
const etl::optional<DataM> opt = etl::make_optional(std::move(test_data));
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK_FALSE(test_data.valid);
|
||||
CHECK_EQUAL(test_value, opt.value().value);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
TEST(test_make_optional_1_constexpr)
|
||||
{
|
||||
constexpr etl::optional<int> opt = etl::make_optional(42);
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK_EQUAL(42, opt.value());
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(test_make_optional_2_lvalue)
|
||||
{
|
||||
std::string test_value("TEST");
|
||||
const etl::optional<Data> opt = etl::make_optional<Data>(test_value);
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK_EQUAL(test_value, opt.value().value);
|
||||
}
|
||||
|
||||
TEST(test_make_optional_2_rvalue)
|
||||
{
|
||||
const etl::optional<DataM> opt = etl::make_optional<DataM>(42u);
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK_EQUAL(42, opt.value().value);
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP14
|
||||
TEST(test_make_optional_2_constexpr)
|
||||
{
|
||||
constexpr etl::optional<uint32_t> opt = etl::make_optional<uint32_t>(42);
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK_EQUAL(42, opt.value());
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(test_make_optional_3)
|
||||
{
|
||||
int test_value1(1);
|
||||
const int test_value2(2);
|
||||
const etl::optional<TestIL> opt = etl::make_optional<TestIL>({10, 11, 12}, test_value1, test_value2, 3);
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK_EQUAL(10, opt->arr[0]);
|
||||
CHECK_EQUAL(11, opt->arr[1]);
|
||||
CHECK_EQUAL(12, opt->arr[2]);
|
||||
CHECK_EQUAL(test_value1, opt->a);
|
||||
CHECK_EQUAL(test_value2, opt->b);
|
||||
CHECK_EQUAL(3, opt->c);
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP20 && ETL_USING_STL
|
||||
TEST(test_make_optional_3_constexpr)
|
||||
{
|
||||
constexpr etl::optional<TestIL> opt = etl::make_optional<TestIL>({1, 2}, 10, 20, 30);
|
||||
CHECK_TRUE(opt.has_value());
|
||||
CHECK_EQUAL(1, opt->arr[0]);
|
||||
CHECK_EQUAL(2, opt->arr[1]);
|
||||
CHECK_EQUAL(0, opt->arr[2]);
|
||||
CHECK_EQUAL(10, opt->a);
|
||||
CHECK_EQUAL(20, opt->b);
|
||||
CHECK_EQUAL(30, opt->c);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
// Tests for noexcept properties of etl::optional
|
||||
// The noexcept specs only take effect when ETL_USING_EXCEPTIONS is enabled,
|
||||
@ -1185,16 +1360,17 @@ namespace
|
||||
// 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
|
||||
struct NothrowAtAll
|
||||
{
|
||||
NothrowCopyMove() noexcept {}
|
||||
NothrowCopyMove(const NothrowCopyMove&) noexcept {}
|
||||
NothrowCopyMove(NothrowCopyMove&&) noexcept {}
|
||||
NothrowCopyMove& operator=(const NothrowCopyMove&) noexcept
|
||||
NothrowAtAll() noexcept {}
|
||||
NothrowAtAll(const NothrowAtAll&) noexcept {}
|
||||
NothrowAtAll(NothrowAtAll&&) noexcept {}
|
||||
NothrowAtAll(std::initializer_list<int>) noexcept {}
|
||||
NothrowAtAll& operator=(const NothrowAtAll&) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
NothrowCopyMove& operator=(NothrowCopyMove&&) noexcept
|
||||
NothrowAtAll& operator=(NothrowAtAll&&) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
@ -1205,10 +1381,10 @@ namespace
|
||||
ThrowingCopy() noexcept {}
|
||||
ThrowingCopy(const ThrowingCopy&) {} // may throw
|
||||
ThrowingCopy(ThrowingCopy&&) noexcept {}
|
||||
ThrowingCopy& operator=(const ThrowingCopy&)
|
||||
ThrowingCopy& operator=(const ThrowingCopy&) // may throw
|
||||
{
|
||||
return *this;
|
||||
} // may throw
|
||||
}
|
||||
ThrowingCopy& operator=(ThrowingCopy&&) noexcept
|
||||
{
|
||||
return *this;
|
||||
@ -1224,22 +1400,23 @@ namespace
|
||||
{
|
||||
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&)
|
||||
ThrowingMove& operator=(ThrowingMove&&) // may throw
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
ThrowingBoth& operator=(ThrowingBoth&&)
|
||||
};
|
||||
|
||||
struct ThrowingAll
|
||||
{
|
||||
ThrowingAll() {} // may throw
|
||||
ThrowingAll(const ThrowingAll&) {} // may throw
|
||||
ThrowingAll(ThrowingAll&&) {} // may throw
|
||||
ThrowingAll(std::initializer_list<int>) {} // may throw
|
||||
ThrowingAll& operator=(const ThrowingAll&) // may throw
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
ThrowingAll& operator=(ThrowingAll&&) // may throw
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
@ -1249,14 +1426,14 @@ namespace
|
||||
{
|
||||
// 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");
|
||||
static_assert(etl::is_nothrow_copy_constructible<etl::optional<NothrowAtAll>>::value,
|
||||
"optional<NothrowAtAll> 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");
|
||||
static_assert(!etl::is_nothrow_copy_constructible<etl::optional<ThrowingAll>>::value,
|
||||
"optional<ThrowingAll> should NOT be nothrow copy constructible");
|
||||
|
||||
// ThrowingMove has nothrow copy but throwing move
|
||||
static_assert(etl::is_nothrow_copy_constructible<etl::optional<ThrowingMove>>::value,
|
||||
@ -1267,20 +1444,29 @@ namespace
|
||||
|
||||
TEST(test_optional_nothrow_move_constructible)
|
||||
{
|
||||
// When T is nothrow move constructible, optional<T> should be too
|
||||
// When T is nothrow move constructible, optional<T> (and swap) 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");
|
||||
static_assert(etl::is_nothrow_move_constructible<etl::optional<NothrowAtAll>>::value,
|
||||
"optional<NothrowAtAll> should be nothrow move constructible");
|
||||
static_assert(noexcept(swap(std::declval<etl::optional<int>&>(), std::declval<etl::optional<int>&>())), "swap<int>() should be nothrow");
|
||||
static_assert(noexcept(swap(std::declval<etl::optional<NothrowAtAll>&>(), std::declval<etl::optional<NothrowAtAll>&>())),
|
||||
"swap<NothrowAtAll>() should be nothrow");
|
||||
|
||||
// When T is NOT nothrow move constructible, optional<T> should not be either
|
||||
// When T is NOT nothrow move constructible, optional<T> (and swap) 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");
|
||||
static_assert(!etl::is_nothrow_move_constructible<etl::optional<ThrowingAll>>::value,
|
||||
"optional<ThrowingAll> should NOT be nothrow move constructible");
|
||||
static_assert(!noexcept(swap(std::declval<etl::optional<ThrowingMove>&>(), std::declval<etl::optional<ThrowingMove>&>())),
|
||||
"swap<ThrowingMove>() should NOT be nothrow");
|
||||
static_assert(!noexcept(swap(std::declval<etl::optional<ThrowingAll>&>(), std::declval<etl::optional<ThrowingAll>&>())),
|
||||
"swap<ThrowingAll>() should NOT be nothrow");
|
||||
|
||||
// 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");
|
||||
static_assert(noexcept(swap(std::declval<etl::optional<ThrowingCopy>&>(), std::declval<etl::optional<ThrowingCopy>&>())),
|
||||
"swap<ThrowingCopy>() should be nothrow");
|
||||
|
||||
CHECK(true); // Placeholder for the static_asserts above
|
||||
}
|
||||
@ -1289,12 +1475,12 @@ namespace
|
||||
{
|
||||
// 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<NothrowAtAll>>::value,
|
||||
"optional<NothrowAtAll> 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");
|
||||
static_assert(etl::is_nothrow_default_constructible<etl::optional<ThrowingAll>>::value,
|
||||
"optional<ThrowingAll> should be nothrow default constructible");
|
||||
|
||||
CHECK(true);
|
||||
}
|
||||
@ -1312,8 +1498,7 @@ namespace
|
||||
{
|
||||
// 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");
|
||||
static_assert(etl::is_nothrow_copy_assignable<etl::optional<NothrowAtAll>>::value, "optional<NothrowAtAll> 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,
|
||||
@ -1326,8 +1511,7 @@ namespace
|
||||
{
|
||||
// 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");
|
||||
static_assert(etl::is_nothrow_move_assignable<etl::optional<NothrowAtAll>>::value, "optional<NothrowAtAll> 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,
|
||||
@ -1335,6 +1519,21 @@ namespace
|
||||
|
||||
CHECK(true);
|
||||
}
|
||||
|
||||
TEST(test_make_optional_nothrow)
|
||||
{
|
||||
// make_optional #1
|
||||
static_assert(noexcept(etl::make_optional(NothrowAtAll{})), "make_optional(NothrowAtAll) should be nothrow");
|
||||
static_assert(!noexcept(etl::make_optional(ThrowingAll{})), "make_optional(ThrowingAll) should NOT be nothrow");
|
||||
|
||||
// make_optional #2
|
||||
static_assert(noexcept(etl::make_optional<NothrowAtAll>()), "make_optional<NothrowAtAll>() should be nothrow");
|
||||
static_assert(!noexcept(etl::make_optional<ThrowingAll>()), "make_optional<ThrowingAll>() should NOT be nothrow");
|
||||
|
||||
// make_optional #3
|
||||
static_assert(noexcept(etl::make_optional<NothrowAtAll>({1, 2, 3})), "make_optional<NothrowAtAll>(1,2,3) should be nothrow");
|
||||
static_assert(!noexcept(etl::make_optional<ThrowingAll>({1, 2, 3})), "make_optional<ThrowingAll>({1,2,3}) should NOT be nothrow");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user