Skip to content

Commit ed5d179

Browse files
committed
More tests on exception safety
1 parent dc5124c commit ed5d179

File tree

3 files changed

+78
-19
lines changed

3 files changed

+78
-19
lines changed

include/aws/crt/Variant.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,9 @@ namespace Aws
210210
VisitorUtil<0, Ts...>::VisitBinary(this, std::move(other), CopyMoveConstructor());
211211
}
212212

213-
template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> VariantImpl(const T &val)
213+
template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1>
214+
VariantImpl(const T &val) noexcept(
215+
std::is_nothrow_constructible<typename std::decay<T>::type, decltype(val)>::value)
214216
{
215217
static_assert(
216218
VariantDetail::Checker::HasType<typename std::decay<T>::type, Ts...>::value,
@@ -225,7 +227,9 @@ namespace Aws
225227
AWS_ASSERT(m_index != -1);
226228
}
227229

228-
template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> VariantImpl(T &&val)
230+
template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1>
231+
VariantImpl(T &&val) noexcept(
232+
std::is_nothrow_constructible<typename std::decay<T>::type, decltype(val)>::value)
229233
{
230234
static_assert(
231235
VariantDetail::Checker::HasType<typename std::decay<T>::type, Ts...>::value,
@@ -695,12 +699,16 @@ namespace Aws
695699
typename std::enable_if<!std::is_default_constructible<T>::value, bool>::type = true>
696700
Variant() = delete;
697701

698-
template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1> Variant(const T &val) : m_variant(val)
702+
template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1>
703+
Variant(const T &val) noexcept(
704+
std::is_nothrow_constructible<typename std::decay<T>::type, decltype(val)>::value)
705+
: m_variant(val)
699706
{
700707
}
701708

702709
template <typename T, EnableIfOtherIsThisVariantAlternative<T> = 1>
703-
Variant(T &&val) : m_variant(std::forward<T>(val))
710+
Variant(T &&val) noexcept(std::is_nothrow_constructible<typename std::decay<T>::type, decltype(val)>::value)
711+
: m_variant(std::forward<T>(val))
704712
{
705713
}
706714

tests/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,9 @@ add_test_case(VariantAssignmentOperator)
109109
add_test_case(VariantWithMoveOnlyUnderlyingType)
110110
add_test_case(VariantWithCopyOnlyUnderlyingType)
111111
add_test_case(VariantWithNoDefaultConstructibleUnderlyingType)
112-
add_test_case(VariantNothrowConstructible)
113-
add_test_case(VariantThrowConstructible)
112+
add_test_case(VariantExceptionSafety_DefaultConstructor)
113+
add_test_case(VariantExceptionSafety_MoveConstructor)
114+
add_test_case(VariantExceptionSafety_CopyConstructor)
114115
add_test_case(VariantEmplace)
115116
add_test_case(VariantVisitor)
116117
add_test_case(StreamTestCreateDestroyWrapper)

tests/VariantTest.cpp

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -322,43 +322,93 @@ static int s_VariantWithNoDefaultConstructibleUnderlyingType(struct aws_allocato
322322

323323
AWS_TEST_CASE(VariantWithNoDefaultConstructibleUnderlyingType, s_VariantWithNoDefaultConstructibleUnderlyingType)
324324

325-
static int s_VariantNothrowConstructible(struct aws_allocator *allocator, void *ctx)
325+
static int s_VariantExceptionSafety_DefaultConstructor(struct aws_allocator *allocator, void *ctx)
326326
{
327327
(void)ctx;
328328

329329
Aws::Crt::ApiHandle apiHandle(allocator);
330330

331-
struct NothrowConstructibleTestType
331+
struct NothrowDefaultConstructibleTestType
332332
{
333-
NothrowConstructibleTestType() noexcept = default;
333+
NothrowDefaultConstructibleTestType() noexcept = default;
334+
NothrowDefaultConstructibleTestType(const NothrowDefaultConstructibleTestType &) noexcept(false) = default;
335+
NothrowDefaultConstructibleTestType(NothrowDefaultConstructibleTestType &&) noexcept(false) = default;
334336
};
335-
using NothrowConstructibleVariant = Aws::Crt::Variant<NothrowConstructibleTestType>;
336-
ASSERT_TRUE(std::is_nothrow_constructible<NothrowConstructibleVariant>::value);
337+
338+
using NothrowDefaultConstructibleVariant = Aws::Crt::Variant<NothrowDefaultConstructibleTestType>;
339+
340+
ASSERT_TRUE(std::is_nothrow_constructible<NothrowDefaultConstructibleVariant>::value);
341+
ASSERT_FALSE((
342+
std::is_nothrow_constructible<NothrowDefaultConstructibleVariant, const NothrowDefaultConstructibleTestType &>::
343+
value));
344+
ASSERT_FALSE(
345+
(std::is_nothrow_constructible<NothrowDefaultConstructibleVariant, NothrowDefaultConstructibleTestType &&>::
346+
value));
337347

338348
return AWS_OP_SUCCESS;
339349
}
340350

341-
AWS_TEST_CASE(VariantNothrowConstructible, s_VariantNothrowConstructible)
351+
AWS_TEST_CASE(VariantExceptionSafety_DefaultConstructor, s_VariantExceptionSafety_DefaultConstructor)
342352

343-
static int s_VariantThrowConstructible(struct aws_allocator *allocator, void *ctx)
353+
static int s_VariantExceptionSafety_MoveConstructor(struct aws_allocator *allocator, void *ctx)
344354
{
345355
(void)ctx;
346356

347357
Aws::Crt::ApiHandle apiHandle(allocator);
348358

349-
struct ThrowConstructibleTestType
359+
struct NothrowMoveConstructibleTestType
350360
{
351-
// Must be user-defined to be non-nothrow.
352-
ThrowConstructibleTestType() {}
361+
NothrowMoveConstructibleTestType(NothrowMoveConstructibleTestType &&) noexcept = default;
362+
363+
NothrowMoveConstructibleTestType() noexcept(false) = default;
364+
NothrowMoveConstructibleTestType(const NothrowMoveConstructibleTestType &) noexcept(false) = default;
353365
};
354366

355-
using ThrowConstructibleVariant = Aws::Crt::Variant<ThrowConstructibleTestType>;
356-
ASSERT_FALSE(std::is_nothrow_constructible<ThrowConstructibleVariant>::value);
367+
using NothrowMoveConstructibleVariant = Aws::Crt::Variant<NothrowMoveConstructibleTestType>;
368+
369+
ASSERT_TRUE(
370+
(std::is_nothrow_constructible<NothrowMoveConstructibleVariant, NothrowMoveConstructibleTestType &&>::value));
371+
ASSERT_FALSE(std::is_nothrow_constructible<NothrowMoveConstructibleVariant>::value);
372+
ASSERT_FALSE(
373+
(std::is_nothrow_constructible<NothrowMoveConstructibleVariant, const NothrowMoveConstructibleTestType &>::
374+
value));
375+
376+
return AWS_OP_SUCCESS;
377+
}
378+
379+
AWS_TEST_CASE(VariantExceptionSafety_MoveConstructor, s_VariantExceptionSafety_MoveConstructor)
380+
381+
static int s_VariantExceptionSafety_CopyConstructor(struct aws_allocator *allocator, void *ctx)
382+
{
383+
(void)ctx;
384+
385+
Aws::Crt::ApiHandle apiHandle(allocator);
386+
387+
struct NothrowCopyConstructibleTestType
388+
{
389+
NothrowCopyConstructibleTestType(const NothrowCopyConstructibleTestType &) noexcept = default;
390+
391+
NothrowCopyConstructibleTestType() noexcept(false) = default;
392+
NothrowCopyConstructibleTestType(NothrowCopyConstructibleTestType &&) noexcept(false) = default;
393+
394+
NothrowCopyConstructibleTestType &operator=(const NothrowCopyConstructibleTestType &) = default;
395+
NothrowCopyConstructibleTestType &operator=(NothrowCopyConstructibleTestType &&) = default;
396+
};
397+
398+
using NothrowCopyConstructibleVariant = Aws::Crt::Variant<NothrowCopyConstructibleTestType>;
399+
400+
ASSERT_TRUE(
401+
(std::is_nothrow_constructible<NothrowCopyConstructibleVariant, const NothrowCopyConstructibleTestType &>::
402+
value));
403+
404+
ASSERT_FALSE(std::is_nothrow_constructible<NothrowCopyConstructibleVariant>::value);
405+
ASSERT_FALSE(
406+
(std::is_nothrow_constructible<NothrowCopyConstructibleVariant, NothrowCopyConstructibleTestType &&>::value));
357407

358408
return AWS_OP_SUCCESS;
359409
}
360410

361-
AWS_TEST_CASE(VariantThrowConstructible, s_VariantThrowConstructible)
411+
AWS_TEST_CASE(VariantExceptionSafety_CopyConstructor, s_VariantExceptionSafety_CopyConstructor)
362412

363413
struct TestStringOnlyVisitor
364414
{

0 commit comments

Comments
 (0)