From f2152f8e54a4ac4c1df832634209d247fb6f96ce Mon Sep 17 00:00:00 2001 From: Simon Brand Date: Mon, 27 Nov 2017 14:24:22 +0000 Subject: [PATCH] Emplace tests --- expected.hpp | 13 +++++++++++-- tests/emplace.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/expected.hpp b/expected.hpp index c764efe..a923e0a 100644 --- a/expected.hpp +++ b/expected.hpp @@ -242,6 +242,9 @@ using expected_enable_from_other = detail::enable_if_t< /// \exclude namespace detail { +struct no_init_t{}; +static constexpr no_init_t no_init{}; + // Implements the storage of the values, and ensures that the destructor is // trivial if it can be. // @@ -252,6 +255,7 @@ template ::value, bool = std::is_trivially_destructible::value> struct expected_storage_base { constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_has_val(false) {} template ::value> * = @@ -297,6 +301,7 @@ struct expected_storage_base { // so the destructor of the `expected` can be trivial. template struct expected_storage_base { constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_has_val(false) {} template ::value> * = @@ -335,6 +340,7 @@ template struct expected_storage_base { // T is trivial, E is not. template struct expected_storage_base { constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_has_val(false) {} template ::value> * = @@ -378,6 +384,7 @@ template struct expected_storage_base { // E is trivial, T is not. template struct expected_storage_base { constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {} + constexpr expected_storage_base(no_init_t) : m_has_val(false) {} template ::value> * = @@ -581,7 +588,8 @@ struct expected_copy_base : expected_operations_base { using expected_operations_base::expected_operations_base; expected_copy_base() = default; - expected_copy_base(const expected_copy_base &rhs) { + expected_copy_base(const expected_copy_base &rhs) : + expected_operations_base(no_init) { if (rhs.has_value()) { this->construct(rhs.get()); } else { @@ -616,7 +624,8 @@ struct expected_move_base : expected_copy_base { expected_move_base(const expected_move_base &rhs) = default; expected_move_base(expected_move_base &&rhs) noexcept( - std::is_nothrow_move_constructible::value) { + std::is_nothrow_move_constructible::value) : + expected_copy_base(no_init) { if (rhs.has_value()) { this->construct(std::move(rhs.get())); } else { diff --git a/tests/emplace.cpp b/tests/emplace.cpp index 6169541..c3b6023 100644 --- a/tests/emplace.cpp +++ b/tests/emplace.cpp @@ -1,4 +1,50 @@ #include "catch.hpp" #include "expected.hpp" +#include +#include +#include + +namespace { +struct takes_init_and_variadic { + std::vector v; + std::tuple t; + template + takes_init_and_variadic(std::initializer_list l, Args &&... args) + : v(l), t(std::forward(args)...) {} +}; +} TEST_CASE("Emplace", "[emplace]") { + { + tl::expected,int> e; + e.emplace(new int{42}); + REQUIRE(e); + REQUIRE(**e == 42); + } + + { + tl::expected,int> e; + e.emplace({0,1}); + REQUIRE(e); + REQUIRE((*e)[0] == 0); + REQUIRE((*e)[1] == 1); + } + + { + tl::expected,int> e; + e.emplace(2,3); + REQUIRE(e); + REQUIRE(std::get<0>(*e) == 2); + REQUIRE(std::get<1>(*e) == 3); + } + + { + tl::expected e = tl::make_unexpected(0); + e.emplace({0,1}, 2, 3); + REQUIRE(e); + REQUIRE(e->v[0] == 0); + REQUIRE(e->v[1] == 1); + REQUIRE(std::get<0>(e->t) == 2); + REQUIRE(std::get<1>(e->t) == 3); + } +}