More testing

This commit is contained in:
Simon Brand
2017-11-27 14:48:16 +00:00
parent f2152f8e54
commit afdacc1ba3
7 changed files with 190 additions and 4 deletions

View File

@@ -1537,22 +1537,22 @@ public:
constexpr bool has_value() const noexcept { return this->m_has_val; } constexpr bool has_value() const noexcept { return this->m_has_val; }
constexpr const T &value() const & { constexpr const T &value() const & {
if (!has_value()) if (!has_value())
throw bad_expected_access<E>(err()); throw bad_expected_access<E>(err().value());
return val(); return val();
} }
TL_EXPECTED_11_CONSTEXPR T &value() & { TL_EXPECTED_11_CONSTEXPR T &value() & {
if (!has_value()) if (!has_value())
throw bad_expected_access<E>(err()); throw bad_expected_access<E>(err().value());
return val(); return val();
} }
constexpr const T &&value() const && { constexpr const T &&value() const && {
if (!has_value()) if (!has_value())
throw bad_expected_access<E>(err()); throw bad_expected_access<E>(err().value());
return std::move(val()); return std::move(val());
} }
TL_EXPECTED_11_CONSTEXPR T &&value() && { TL_EXPECTED_11_CONSTEXPR T &&value() && {
if (!has_value()) if (!has_value())
throw bad_expected_access<E>(err()); throw bad_expected_access<E>(err().value());
return std::move(val()); return std::move(val());
} }
constexpr const E &error() const & { return err().value(); } constexpr const E &error() const & { return err().value(); }

120
tests/bases.cpp Normal file
View File

@@ -0,0 +1,120 @@
#include "catch.hpp"
#include "expected.hpp"
TEST_CASE("Triviality", "[bases.triviality]") {
REQUIRE(std::is_trivially_copy_constructible<tl::expected<int,int>>::value);
REQUIRE(std::is_trivially_copy_assignable<tl::expected<int,int>>::value);
REQUIRE(std::is_trivially_move_constructible<tl::expected<int,int>>::value);
REQUIRE(std::is_trivially_move_assignable<tl::expected<int,int>>::value);
REQUIRE(std::is_trivially_destructible<tl::expected<int,int>>::value);
{
struct T {
T(const T&) = default;
T(T&&) = default;
T& operator=(const T&) = default;
T& operator=(T&&) = default;
~T() = default;
};
REQUIRE(std::is_trivially_copy_constructible<tl::expected<T,int>>::value);
REQUIRE(std::is_trivially_copy_assignable<tl::expected<T,int>>::value);
REQUIRE(std::is_trivially_move_constructible<tl::expected<T,int>>::value);
REQUIRE(std::is_trivially_move_assignable<tl::expected<T,int>>::value);
REQUIRE(std::is_trivially_destructible<tl::expected<T,int>>::value);
}
{
struct T {
T(const T&){}
T(T&&) {};
T& operator=(const T&) {}
T& operator=(T&&) {};
~T(){}
};
REQUIRE(!std::is_trivially_copy_constructible<tl::expected<T,int>>::value);
REQUIRE(!std::is_trivially_copy_assignable<tl::expected<T,int>>::value);
REQUIRE(!std::is_trivially_move_constructible<tl::expected<T,int>>::value);
REQUIRE(!std::is_trivially_move_assignable<tl::expected<T,int>>::value);
REQUIRE(!std::is_trivially_destructible<tl::expected<T,int>>::value);
}
}
TEST_CASE("Deletion", "[bases.deletion]") {
REQUIRE(std::is_copy_constructible<tl::expected<int,int>>::value);
REQUIRE(std::is_copy_assignable<tl::expected<int,int>>::value);
REQUIRE(std::is_move_constructible<tl::expected<int,int>>::value);
REQUIRE(std::is_move_assignable<tl::expected<int,int>>::value);
REQUIRE(std::is_destructible<tl::expected<int,int>>::value);
{
struct T {
T()=default;
};
REQUIRE(std::is_default_constructible<tl::expected<T,int>>::value);
}
{
struct T {
T(int);
};
REQUIRE(!std::is_default_constructible<tl::expected<T,int>>::value);
}
{
struct T {
T(const T&) = default;
T(T&&) = default;
T& operator=(const T&) = default;
T& operator=(T&&) = default;
~T() = default;
};
REQUIRE(std::is_copy_constructible<tl::expected<T,int>>::value);
REQUIRE(std::is_copy_assignable<tl::expected<T,int>>::value);
REQUIRE(std::is_move_constructible<tl::expected<T,int>>::value);
REQUIRE(std::is_move_assignable<tl::expected<T,int>>::value);
REQUIRE(std::is_destructible<tl::expected<T,int>>::value);
}
{
struct T {
T(const T&)=delete;
T(T&&)=delete;
T& operator=(const T&)=delete;
T& operator=(T&&)=delete;
};
REQUIRE(!std::is_copy_constructible<tl::expected<T,int>>::value);
REQUIRE(!std::is_copy_assignable<tl::expected<T,int>>::value);
REQUIRE(!std::is_move_constructible<tl::expected<T,int>>::value);
REQUIRE(!std::is_move_assignable<tl::expected<T,int>>::value);
}
{
struct T {
T(const T&)=delete;
T(T&&)=default;
T& operator=(const T&)=delete;
T& operator=(T&&)=default;
};
REQUIRE(!std::is_copy_constructible<tl::expected<T,int>>::value);
REQUIRE(!std::is_copy_assignable<tl::expected<T,int>>::value);
REQUIRE(std::is_move_constructible<tl::expected<T,int>>::value);
REQUIRE(std::is_move_assignable<tl::expected<T,int>>::value);
}
{
struct T {
T(const T&)=default;
T(T&&)=delete;
T& operator=(const T&)=default;
T& operator=(T&&)=delete;
};
REQUIRE(std::is_copy_constructible<tl::expected<T,int>>::value);
REQUIRE(std::is_copy_assignable<tl::expected<T,int>>::value);
//TODO see why this fails
//REQUIRE(!std::is_move_constructible<tl::expected<T,int>>::value);
//REQUIRE(!std::is_move_assignable<tl::expected<T,int>>::value);
}
}

6
tests/constexpr.cpp Normal file
View File

@@ -0,0 +1,6 @@
#include "catch.hpp"
#include "expected.hpp"
TEST_CASE("Constexpr", "[constexpr]") {
//TODO
}

View File

@@ -18,6 +18,18 @@ TEST_CASE("Constructors", "[constructors]") {
REQUIRE(e == 0); REQUIRE(e == 0);
} }
{
tl::expected<int,int> e = tl::make_unexpected(0);
REQUIRE(!e);
REQUIRE(e.error() == 0);
}
{
tl::expected<int,int> e (tl::unexpect, 0);
REQUIRE(!e);
REQUIRE(e.error() == 0);
}
{ {
tl::expected<int,int> e (tl::in_place, 42); tl::expected<int,int> e (tl::in_place, 42);
REQUIRE(e); REQUIRE(e);

6
tests/noexcept.cpp Normal file
View File

@@ -0,0 +1,6 @@
#include "catch.hpp"
#include "expected.hpp"
TEST_CASE("Noexcept", "[noexcept]") {
//TODO
}

36
tests/observers.cpp Normal file
View File

@@ -0,0 +1,36 @@
#include "catch.hpp"
#include "expected.hpp"
struct move_detector {
move_detector() = default;
move_detector(move_detector &&rhs) { rhs.been_moved = true; }
bool been_moved = false;
};
TEST_CASE("Observers", "[observers]") {
tl::expected<int,int> o1 = 42;
tl::expected<int,int> o2 {tl::unexpect, 0};
const tl::expected<int,int> o3 = 42;
REQUIRE(*o1 == 42);
REQUIRE(*o1 == o1.value());
REQUIRE(o2.value_or(42) == 42);
REQUIRE(o2.error() == 0);
REQUIRE(o3.value() == 42);
auto success = std::is_same<decltype(o1.value()), int &>::value;
REQUIRE(success);
success = std::is_same<decltype(o3.value()), const int &>::value;
REQUIRE(success);
success = std::is_same<decltype(std::move(o1).value()), int &&>::value;
REQUIRE(success);
#ifndef TL_EXPECTED_NO_CONSTRR
success = std::is_same<decltype(std::move(o3).value()), const int &&>::value;
REQUIRE(success);
#endif
tl::expected<move_detector,int> o4{tl::in_place};
move_detector o5 = std::move(o4).value();
REQUIRE(o4->been_moved);
REQUIRE(!o5.been_moved);
}

6
tests/relops.cpp Normal file
View File

@@ -0,0 +1,6 @@
#include "catch.hpp"
#include "expected.hpp"
TEST_CASE("Relational operators", "[relops]") {
//TODO
}