From 8338bb7ac635fc5d0f766b0b8dc86d810d3521fb Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 8 Jun 2023 11:45:23 +0200 Subject: tests: port iterable tests --- source/tests/CMakeLists.txt | 2 +- source/tests/src/iterable.cpp | 1063 +++++++++++++++++++++++++++++++++++ source/tests/src/iterable_suite.cpp | 719 ----------------------- 3 files changed, 1064 insertions(+), 720 deletions(-) create mode 100644 source/tests/src/iterable.cpp delete mode 100644 source/tests/src/iterable_suite.cpp diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index 7d08e12..77a0a66 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -14,7 +14,7 @@ add_executable("${PROJECT_NAME}_tests" "src/equality_comparison.cpp" "src/hash.cpp" "src/io_operators.cpp" - # "src/iterable_suite.cpp" + "src/iterable.cpp" # "src/relational_operators_suite.cpp" ) diff --git a/source/tests/src/iterable.cpp b/source/tests/src/iterable.cpp new file mode 100644 index 0000000..265dc8c --- /dev/null +++ b/source/tests/src/iterable.cpp @@ -0,0 +1,1063 @@ +#include "newtype/derivable.hpp" +#include "newtype/deriving.hpp" +#include "newtype/impl/type_traits_extensions.hpp" +#include "newtype/newtype.hpp" + +#include + +#include +#include +#include +#include + +namespace iterable_types +{ + + struct with_member + { + using iterator = char *; + using const_iterator = char const *; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + auto constexpr begin() -> iterator; + auto constexpr begin() const -> const_iterator; + auto constexpr cbegin() const -> const_iterator; + auto constexpr rbegin() -> reverse_iterator; + auto constexpr rbegin() const -> const_reverse_iterator; + auto constexpr crbegin() const -> const_reverse_iterator; + + auto constexpr end() -> iterator; + auto constexpr end() const -> const_iterator; + auto constexpr cend() const -> const_iterator; + auto constexpr rend() -> reverse_iterator; + auto constexpr rend() const -> const_reverse_iterator; + auto constexpr crend() const -> const_reverse_iterator; + }; + + struct with_free + { + using iterator = char *; + using const_iterator = char const *; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + }; + + auto constexpr begin(with_free &) -> with_free::iterator; + auto constexpr begin(with_free const &) -> with_free::const_iterator; + auto constexpr cbegin(with_free const &) -> with_free::const_iterator; + auto constexpr rbegin(with_free &) -> with_free::reverse_iterator; + auto constexpr rbegin(with_free const &) -> with_free::const_reverse_iterator; + auto constexpr crbegin(with_free const &) -> with_free::const_reverse_iterator; + auto constexpr end(with_free &) -> with_free::iterator; + auto constexpr end(with_free const &) -> with_free::const_iterator; + auto constexpr cend(with_free const &) -> with_free::const_iterator; + auto constexpr rend(with_free &) -> with_free::reverse_iterator; + auto constexpr rend(with_free const &) -> with_free::const_reverse_iterator; + auto constexpr crend(with_free const &) -> with_free::const_reverse_iterator; + +} // namespace iterable_types + +SCENARIO("Iterators", "[iterators]") +{ + GIVEN("A new_type over a non-iterable base type not deriving nt::Iterable") + { + using type_alias = nt::new_type; + static_assert(!nt::impl::has_begin_v); + static_assert(!nt::impl::has_begin_v); + static_assert(!nt::impl::has_cbegin_v); + static_assert(!nt::impl::has_rbegin_v); + static_assert(!nt::impl::has_rbegin_v); + static_assert(!nt::impl::has_crbegin_v); + static_assert(!nt::impl::has_end_v); + static_assert(!nt::impl::has_end_v); + static_assert(!nt::impl::has_cend_v); + static_assert(!nt::impl::has_rend_v); + static_assert(!nt::impl::has_rend_v); + static_assert(!nt::impl::has_crend_v); + + THEN("it has no begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_begin_v); + } + + THEN("it has no constant begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_begin_v); + } + + THEN("it has no cbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_cbegin_v); + } + + THEN("it has no rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_rbegin_v); + } + + THEN("it has no constant rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_rbegin_v); + } + + THEN("it has no crbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_crbegin_v); + } + + THEN("it has no end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_end_v); + } + + THEN("it has no constant end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_end_v); + } + + THEN("it has no cend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_cend_v); + } + + THEN("it has no rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_rend_v); + } + + THEN("it has no constant rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_rend_v); + } + + THEN("it has no crend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_crend_v); + } + } + + GIVEN("A new_type over a non-iterable base type deriving nt::Iterable") + { + using type_alias = nt::new_type; + static_assert(!nt::impl::has_begin_v); + static_assert(!nt::impl::has_begin_v); + static_assert(!nt::impl::has_cbegin_v); + static_assert(!nt::impl::has_rbegin_v); + static_assert(!nt::impl::has_rbegin_v); + static_assert(!nt::impl::has_crbegin_v); + static_assert(!nt::impl::has_end_v); + static_assert(!nt::impl::has_end_v); + static_assert(!nt::impl::has_cend_v); + static_assert(!nt::impl::has_rend_v); + static_assert(!nt::impl::has_rend_v); + static_assert(!nt::impl::has_crend_v); + + THEN("it has no begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_begin_v); + } + + THEN("it has no constant begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_begin_v); + } + + THEN("it has no cbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_cbegin_v); + } + + THEN("it has no rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_rbegin_v); + } + + THEN("it has no constant rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_rbegin_v); + } + + THEN("it has no crbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_crbegin_v); + } + + THEN("it has no end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_end_v); + } + + THEN("it has no constant end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_end_v); + } + + THEN("it has no cend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_cend_v); + } + + THEN("it has no rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_rend_v); + } + + THEN("it has no constant rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_rend_v); + } + + THEN("it has no crend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_crend_v); + } + } + + GIVEN("A new_type over an iterable base type not deriving nt::Iterable") + { + using type_alias = nt::new_type, struct tag>; + static_assert(nt::impl::has_begin_v); + static_assert(nt::impl::has_begin_v); + static_assert(nt::impl::has_cbegin_v); + static_assert(nt::impl::has_rbegin_v); + static_assert(nt::impl::has_rbegin_v); + static_assert(nt::impl::has_crbegin_v); + static_assert(nt::impl::has_end_v); + static_assert(nt::impl::has_end_v); + static_assert(nt::impl::has_cend_v); + static_assert(nt::impl::has_rend_v); + static_assert(nt::impl::has_rend_v); + static_assert(nt::impl::has_crend_v); + + THEN("it has no begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_begin_v); + } + + THEN("it has no constant begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_begin_v); + } + + THEN("it has no cbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_cbegin_v); + } + + THEN("it has no rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_rbegin_v); + } + + THEN("it has no constant rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_rbegin_v); + } + + THEN("it has no crbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_crbegin_v); + } + + THEN("it has no end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_end_v); + } + + THEN("it has no constant end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_end_v); + } + + THEN("it has no cend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_cend_v); + } + + THEN("it has no rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_rend_v); + } + + THEN("it has no constant rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_rend_v); + } + + THEN("it has no crend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_crend_v); + } + } + + GIVEN("A new_type over an iterable base type deriving nt::Iterable") + { + using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; + static_assert(nt::impl::has_begin_v); + static_assert(nt::impl::has_begin_v); + static_assert(nt::impl::has_cbegin_v); + static_assert(nt::impl::has_rbegin_v); + static_assert(nt::impl::has_rbegin_v); + static_assert(nt::impl::has_crbegin_v); + static_assert(nt::impl::has_end_v); + static_assert(nt::impl::has_end_v); + static_assert(nt::impl::has_cend_v); + static_assert(nt::impl::has_rend_v); + static_assert(nt::impl::has_rend_v); + static_assert(nt::impl::has_crend_v); + + THEN("it has begin") + { + STATIC_REQUIRE(nt::impl::has_begin_v); + } + + THEN("it has constant begin") + { + STATIC_REQUIRE(nt::impl::has_begin_v); + } + + THEN("it has cbegin") + { + STATIC_REQUIRE(nt::impl::has_cbegin_v); + } + + THEN("it has rbegin") + { + STATIC_REQUIRE(nt::impl::has_rbegin_v); + } + + THEN("it has constant rbegin") + { + STATIC_REQUIRE(nt::impl::has_rbegin_v); + } + + THEN("it has crbegin") + { + STATIC_REQUIRE(nt::impl::has_crbegin_v); + } + + THEN("it has end") + { + STATIC_REQUIRE(nt::impl::has_end_v); + } + + THEN("it has constant end") + { + STATIC_REQUIRE(nt::impl::has_end_v); + } + + THEN("it has cend") + { + STATIC_REQUIRE(nt::impl::has_cend_v); + } + + THEN("it has rend") + { + STATIC_REQUIRE(nt::impl::has_rend_v); + } + + THEN("it has constant rend") + { + STATIC_REQUIRE(nt::impl::has_rend_v); + } + + THEN("it has crend") + { + STATIC_REQUIRE(nt::impl::has_crend_v); + } + } +} + +SCENARIO("Iterators (member)", "[iterators]") +{ + GIVEN("A new_type over a non-iterable base type not deriving nt::Iterable") + { + using type_alias = nt::new_type; + static_assert(!nt::impl::has_member_begin_v); + static_assert(!nt::impl::has_member_begin_v); + static_assert(!nt::impl::has_member_cbegin_v); + static_assert(!nt::impl::has_member_rbegin_v); + static_assert(!nt::impl::has_member_rbegin_v); + static_assert(!nt::impl::has_member_crbegin_v); + static_assert(!nt::impl::has_member_end_v); + static_assert(!nt::impl::has_member_end_v); + static_assert(!nt::impl::has_member_cend_v); + static_assert(!nt::impl::has_member_rend_v); + static_assert(!nt::impl::has_member_rend_v); + static_assert(!nt::impl::has_member_crend_v); + + THEN("it has no member begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_begin_v); + } + + THEN("it has no member constant begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_begin_v); + } + + THEN("it has no member cbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_cbegin_v); + } + + THEN("it has no member rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_rbegin_v); + } + + THEN("it has no member constant rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_rbegin_v); + } + + THEN("it has no member crbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_crbegin_v); + } + + THEN("it has no member end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_end_v); + } + + THEN("it has no member constant end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_end_v); + } + + THEN("it has no member cend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_cend_v); + } + + THEN("it has no member rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_rend_v); + } + + THEN("it has no member constant rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_rend_v); + } + + THEN("it has no member crend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_crend_v); + } + } + + GIVEN("A new_type over a non-iterable base type deriving nt::Iterable") + { + using type_alias = nt::new_type; + static_assert(!nt::impl::has_member_begin_v); + static_assert(!nt::impl::has_member_begin_v); + static_assert(!nt::impl::has_member_cbegin_v); + static_assert(!nt::impl::has_member_rbegin_v); + static_assert(!nt::impl::has_member_rbegin_v); + static_assert(!nt::impl::has_member_crbegin_v); + static_assert(!nt::impl::has_member_end_v); + static_assert(!nt::impl::has_member_end_v); + static_assert(!nt::impl::has_member_cend_v); + static_assert(!nt::impl::has_member_rend_v); + static_assert(!nt::impl::has_member_rend_v); + static_assert(!nt::impl::has_member_crend_v); + + THEN("it has no member begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_begin_v); + } + + THEN("it has no member constant begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_begin_v); + } + + THEN("it has no member cbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_cbegin_v); + } + + THEN("it has no member rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_rbegin_v); + } + + THEN("it has no member constant rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_rbegin_v); + } + + THEN("it has no member crbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_crbegin_v); + } + + THEN("it has no member end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_end_v); + } + + THEN("it has no member constant end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_end_v); + } + + THEN("it has no member cend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_cend_v); + } + + THEN("it has no member rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_rend_v); + } + + THEN("it has no member constant rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_rend_v); + } + + THEN("it has no member crend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_crend_v); + } + } + + GIVEN("A new_type over an iterable base type not deriving nt::Iterable") + { + using type_alias = nt::new_type, struct tag>; + static_assert(nt::impl::has_member_begin_v); + static_assert(nt::impl::has_member_begin_v); + static_assert(nt::impl::has_member_cbegin_v); + static_assert(nt::impl::has_member_rbegin_v); + static_assert(nt::impl::has_member_rbegin_v); + static_assert(nt::impl::has_member_crbegin_v); + static_assert(nt::impl::has_member_end_v); + static_assert(nt::impl::has_member_end_v); + static_assert(nt::impl::has_member_cend_v); + static_assert(nt::impl::has_member_rend_v); + static_assert(nt::impl::has_member_rend_v); + static_assert(nt::impl::has_member_crend_v); + + THEN("it has no member begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_begin_v); + } + + THEN("it has no member constant begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_begin_v); + } + + THEN("it has no member cbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_cbegin_v); + } + + THEN("it has no member rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_rbegin_v); + } + + THEN("it has no member constant rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_rbegin_v); + } + + THEN("it has no member crbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_crbegin_v); + } + + THEN("it has no member end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_end_v); + } + + THEN("it has no member constant end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_end_v); + } + + THEN("it has no member cend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_cend_v); + } + + THEN("it has no member rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_rend_v); + } + + THEN("it has no member constant rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_rend_v); + } + + THEN("it has no member crend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_member_crend_v); + } + } + + GIVEN("A new_type over an iterable base type deriving nt::Iterable") + { + using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; + static_assert(nt::impl::has_member_begin_v); + static_assert(nt::impl::has_member_begin_v); + static_assert(nt::impl::has_member_cbegin_v); + static_assert(nt::impl::has_member_rbegin_v); + static_assert(nt::impl::has_member_rbegin_v); + static_assert(nt::impl::has_member_crbegin_v); + static_assert(nt::impl::has_member_end_v); + static_assert(nt::impl::has_member_end_v); + static_assert(nt::impl::has_member_cend_v); + static_assert(nt::impl::has_member_rend_v); + static_assert(nt::impl::has_member_rend_v); + static_assert(nt::impl::has_member_crend_v); + + THEN("it has member begin") + { + STATIC_REQUIRE(nt::impl::has_member_begin_v); + } + + THEN("it has member constant begin") + { + STATIC_REQUIRE(nt::impl::has_member_begin_v); + } + + THEN("it has member cbegin") + { + STATIC_REQUIRE(nt::impl::has_member_cbegin_v); + } + + THEN("it has member rbegin") + { + STATIC_REQUIRE(nt::impl::has_member_rbegin_v); + } + + THEN("it has member constant rbegin") + { + STATIC_REQUIRE(nt::impl::has_member_rbegin_v); + } + + THEN("it has member crbegin") + { + STATIC_REQUIRE(nt::impl::has_member_crbegin_v); + } + + THEN("it has member end") + { + STATIC_REQUIRE(nt::impl::has_member_end_v); + } + + THEN("it has member constant end") + { + STATIC_REQUIRE(nt::impl::has_member_end_v); + } + + THEN("it has member cend") + { + STATIC_REQUIRE(nt::impl::has_member_cend_v); + } + + THEN("it has member rend") + { + STATIC_REQUIRE(nt::impl::has_member_rend_v); + } + + THEN("it has member constant rend") + { + STATIC_REQUIRE(nt::impl::has_member_rend_v); + } + + THEN("it has member crend") + { + STATIC_REQUIRE(nt::impl::has_member_crend_v); + } + } +} + +SCENARIO("Iterators (free)", "[iterators]") +{ + GIVEN("A new_type over a non-iterable base type not deriving nt::Iterable") + { + using type_alias = nt::new_type; + static_assert(!nt::impl::has_free_begin_v); + static_assert(!nt::impl::has_free_begin_v); + static_assert(!nt::impl::has_free_cbegin_v); + static_assert(!nt::impl::has_free_rbegin_v); + static_assert(!nt::impl::has_free_rbegin_v); + static_assert(!nt::impl::has_free_crbegin_v); + static_assert(!nt::impl::has_free_end_v); + static_assert(!nt::impl::has_free_end_v); + static_assert(!nt::impl::has_free_cend_v); + static_assert(!nt::impl::has_free_rend_v); + static_assert(!nt::impl::has_free_rend_v); + static_assert(!nt::impl::has_free_crend_v); + + THEN("it has no free begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_begin_v); + } + + THEN("it has no free constant begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_begin_v); + } + + THEN("it has no free cbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_cbegin_v); + } + + THEN("it has no free rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_rbegin_v); + } + + THEN("it has no free constant rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_rbegin_v); + } + + THEN("it has no free crbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_crbegin_v); + } + + THEN("it has no free end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_end_v); + } + + THEN("it has no free constant end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_end_v); + } + + THEN("it has no free cend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_cend_v); + } + + THEN("it has no free rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_rend_v); + } + + THEN("it has no free constant rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_rend_v); + } + + THEN("it has no free crend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_crend_v); + } + } + + GIVEN("A new_type over a non-iterable base type deriving nt::Iterable") + { + using type_alias = nt::new_type; + static_assert(!nt::impl::has_free_begin_v); + static_assert(!nt::impl::has_free_begin_v); + static_assert(!nt::impl::has_free_cbegin_v); + static_assert(!nt::impl::has_free_rbegin_v); + static_assert(!nt::impl::has_free_rbegin_v); + static_assert(!nt::impl::has_free_crbegin_v); + static_assert(!nt::impl::has_free_end_v); + static_assert(!nt::impl::has_free_end_v); + static_assert(!nt::impl::has_free_cend_v); + static_assert(!nt::impl::has_free_rend_v); + static_assert(!nt::impl::has_free_rend_v); + static_assert(!nt::impl::has_free_crend_v); + + THEN("it has no free begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_begin_v); + } + + THEN("it has no free constant begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_begin_v); + } + + THEN("it has no free cbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_cbegin_v); + } + + THEN("it has no free rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_rbegin_v); + } + + THEN("it has no free constant rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_rbegin_v); + } + + THEN("it has no free crbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_crbegin_v); + } + + THEN("it has no free end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_end_v); + } + + THEN("it has no free constant end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_end_v); + } + + THEN("it has no free cend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_cend_v); + } + + THEN("it has no free rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_rend_v); + } + + THEN("it has no free constant rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_rend_v); + } + + THEN("it has no free crend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_crend_v); + } + } + + GIVEN("A new_type over an iterable base type not deriving nt::Iterable") + { + using type_alias = nt::new_type, struct tag>; + static_assert(nt::impl::has_free_begin_v); + static_assert(nt::impl::has_free_begin_v); + static_assert(nt::impl::has_free_cbegin_v); + static_assert(nt::impl::has_free_rbegin_v); + static_assert(nt::impl::has_free_rbegin_v); + static_assert(nt::impl::has_free_crbegin_v); + static_assert(nt::impl::has_free_end_v); + static_assert(nt::impl::has_free_end_v); + static_assert(nt::impl::has_free_cend_v); + static_assert(nt::impl::has_free_rend_v); + static_assert(nt::impl::has_free_rend_v); + static_assert(nt::impl::has_free_crend_v); + + THEN("it has no free begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_begin_v); + } + + THEN("it has no free constant begin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_begin_v); + } + + THEN("it has no free cbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_cbegin_v); + } + + THEN("it has no free rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_rbegin_v); + } + + THEN("it has no free constant rbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_rbegin_v); + } + + THEN("it has no free crbegin") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_crbegin_v); + } + + THEN("it has no free end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_end_v); + } + + THEN("it has no free constant end") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_end_v); + } + + THEN("it has no free cend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_cend_v); + } + + THEN("it has no free rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_rend_v); + } + + THEN("it has no free constant rend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_rend_v); + } + + THEN("it has no free crend") + { + STATIC_REQUIRE_FALSE(nt::impl::has_free_crend_v); + } + } + + GIVEN("A new_type over an iterable base type deriving nt::Iterable") + { + using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; + static_assert(nt::impl::has_free_begin_v); + static_assert(nt::impl::has_free_begin_v); + static_assert(nt::impl::has_free_cbegin_v); + static_assert(nt::impl::has_free_rbegin_v); + static_assert(nt::impl::has_free_rbegin_v); + static_assert(nt::impl::has_free_crbegin_v); + static_assert(nt::impl::has_free_end_v); + static_assert(nt::impl::has_free_end_v); + static_assert(nt::impl::has_free_cend_v); + static_assert(nt::impl::has_free_rend_v); + static_assert(nt::impl::has_free_rend_v); + static_assert(nt::impl::has_free_crend_v); + + THEN("it has free begin") + { + STATIC_REQUIRE(nt::impl::has_free_begin_v); + } + + THEN("it has free constant begin") + { + STATIC_REQUIRE(nt::impl::has_free_begin_v); + } + + THEN("it has free cbegin") + { + STATIC_REQUIRE(nt::impl::has_free_cbegin_v); + } + + THEN("it has free rbegin") + { + STATIC_REQUIRE(nt::impl::has_free_rbegin_v); + } + + THEN("it has free constant rbegin") + { + STATIC_REQUIRE(nt::impl::has_free_rbegin_v); + } + + THEN("it has free crbegin") + { + STATIC_REQUIRE(nt::impl::has_free_crbegin_v); + } + + THEN("it has free end") + { + STATIC_REQUIRE(nt::impl::has_free_end_v); + } + + THEN("it has free constant end") + { + STATIC_REQUIRE(nt::impl::has_free_end_v); + } + + THEN("it has free cend") + { + STATIC_REQUIRE(nt::impl::has_free_cend_v); + } + + THEN("it has free rend") + { + STATIC_REQUIRE(nt::impl::has_free_rend_v); + } + + THEN("it has free constant rend") + { + STATIC_REQUIRE(nt::impl::has_free_rend_v); + } + + THEN("it has free crend") + { + STATIC_REQUIRE(nt::impl::has_free_crend_v); + } + } +} + +SCENARIO("Iterator Semantics", "[iterators]") +{ + GIVEN("An iterable new_type") + { + using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; + + THEN("a non-const object can be used in value range-based for") + { + auto obj = type_alias{{1, 2, 3}}; + auto res = 0; + for (auto e : obj) + { + res += e; + } + REQUIRE(res == 6); + } + + THEN("a const object can be used in value range-based for") + { + auto const obj = type_alias{{1, 2, 3}}; + auto res = 0; + for (auto e : obj) + { + res += e; + } + REQUIRE(res == 6); + } + + THEN("a non-const object can be used in reference range-based for") + { + auto obj = type_alias{{1, 2, 3}}; + auto res = 0; + for (auto & e : obj) + { + res += e; + } + REQUIRE(res == 6); + } + + THEN("a const object can be used in const-reference range-based for") + { + auto const obj = type_alias{{1, 2, 3}}; + auto res = 0; + for (auto const & e : obj) + { + res += e; + } + REQUIRE(res == 6); + } + + THEN("using an instance of it in an STL algorithm yields the same results as using an instance of the base type") + { + auto const base_obj = type_alias::base_type{{1, 2, 3}}; + auto const nt_obj = type_alias{base_obj}; + + auto base_res = std::accumulate(begin(base_obj), end(base_obj), 0); + auto nt_res = std::accumulate(begin(nt_obj), end(nt_obj), 0); + + REQUIRE(nt_res == base_res); + } + + THEN("iterating over an instance yields the same elements in the same order as iterating over an instance of the base type") + { + auto const base_obj = type_alias::base_type{{1, 2, 3}}; + auto const nt_obj = type_alias{base_obj}; + + REQUIRE(std::equal(cbegin(nt_obj), cend(nt_obj), cbegin(base_obj), cend(base_obj))); + } + } +} diff --git a/source/tests/src/iterable_suite.cpp b/source/tests/src/iterable_suite.cpp deleted file mode 100644 index add4696..0000000 --- a/source/tests/src/iterable_suite.cpp +++ /dev/null @@ -1,719 +0,0 @@ -#include "iterable_suite.hpp" - -#include "kawaii.hpp" -#include "newtype/derivable.hpp" -#include "newtype/deriving.hpp" -#include "newtype/impl/type_traits_extensions.hpp" -#include "newtype/newtype.hpp" - -#include - -#include -#include -#include -#include - -namespace -{ - - struct with_member - { - using iterator = char *; - using const_iterator = char const *; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - auto begin() -> iterator; - auto begin() const -> const_iterator; - auto cbegin() const -> const_iterator; - auto rbegin() -> reverse_iterator; - auto rbegin() const -> const_reverse_iterator; - auto crbegin() const -> const_reverse_iterator; - - auto end() -> iterator; - auto end() const -> const_iterator; - auto cend() const -> const_iterator; - auto rend() -> reverse_iterator; - auto rend() const -> const_reverse_iterator; - auto crend() const -> const_reverse_iterator; - }; - - struct with_free - { - using iterator = char *; - using const_iterator = char const *; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - }; - - auto begin(with_free &) -> with_free::iterator - { - return {}; - } - - auto begin(with_free const &) -> with_free::const_iterator - { - return {}; - } - - auto cbegin(with_free const &) -> with_free::const_iterator - { - return {}; - } - - auto rbegin(with_free &) -> with_free::reverse_iterator - { - return {}; - } - - auto rbegin(with_free const &) -> with_free::const_reverse_iterator - { - return {}; - } - - auto crbegin(with_free const &) -> with_free::const_reverse_iterator - { - return {}; - } - - auto end(with_free &) -> with_free::iterator - { - return {}; - } - - auto end(with_free const &) -> with_free::const_iterator - { - return {}; - } - - auto cend(with_free const &) -> with_free::const_iterator - { - return {}; - } - - auto rend(with_free &) -> with_free::reverse_iterator - { - return {}; - } - - auto rend(with_free const &) -> with_free::const_reverse_iterator - { - return {}; - } - - auto crend(with_free const &) -> with_free::const_reverse_iterator - { - return {}; - } - -} // namespace - -inline namespace combined_enablement_tests -{ - - auto a_new__type_not_deriving_iterable_has_no_begin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_begin_v)); - } - - auto a_new__type_not_deriving_iterable_has_no_constant_begin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_begin_v)); - } - - auto a_new__type_not_deriving_iterable_has_no_cbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_cbegin_v)); - } - - auto a_new__type_not_deriving_iterable_has_no_rbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_rbegin_v)); - } - - auto a_new__type_not_deriving_iterable_has_no_constant_rbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_rbegin_v)); - } - - auto a_new__type_not_deriving_iterable_has_no_crbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_crbegin_v)); - } - - auto a_new__type_not_deriving_iterable_has_no_end() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_end_v)); - } - - auto a_new__type_not_deriving_iterable_has_no_constant_end() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_end_v)); - } - - auto a_new__type_not_deriving_iterable_has_no_cend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_cend_v)); - } - - auto a_new__type_not_deriving_iterable_has_no_rend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_rend_v)); - } - - auto a_new__type_not_deriving_iterable_has_no_constant_rend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_rend_v)); - } - - auto a_new__type_not_deriving_iterable_has_no_crend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_crend_v)); - } - - auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_begin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_begin_v)); - } - - auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_begin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_begin_v)); - } - - auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_cbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_cbegin_v)); - } - - auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_rbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_rbegin_v)); - } - - auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_rbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_rbegin_v)); - } - - auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_crbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_crbegin_v)); - } - - auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_end() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_end_v)); - } - - auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_end() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_end_v)); - } - - auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_cend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_cend_v)); - } - - auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_rend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_rend_v)); - } - - auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_rend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_rend_v)); - } - - auto a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_crend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_crend_v)); - } - -} // namespace combined_enablement_tests - -inline namespace member_enablement_tests -{ - - auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_begin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_member_begin_v)); - } - - auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_begin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_member_begin_v)); - } - - auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_cbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_member_cbegin_v)); - } - - auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_rbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_member_rbegin_v)); - } - - auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_rbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_member_rbegin_v)); - } - - auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_crbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_member_crbegin_v)); - } - - auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_end() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_member_end_v)); - } - - auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_end() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_member_end_v)); - } - - auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_cend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_member_cend_v)); - } - - auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_rend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_member_rend_v)); - } - - auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_rend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_member_rend_v)); - } - - auto a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_crend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_member_crend_v)); - } - - auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_begin() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_begin_v); - } - - auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_begin() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_begin_v); - } - - auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_cbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_cbegin_v); - } - - auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_rbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_rbegin_v); - } - - auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_rbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_rbegin_v); - } - - auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_crbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_crbegin_v); - } - - auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_end() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_end_v); - } - - auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_end() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_end_v); - } - - auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_cend() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_cend_v); - } - - auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_rend() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_rend_v); - } - - auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_rend() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_rend_v); - } - - auto a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_crend() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_member_crend_v); - } - -} // namespace member_enablement_tests - -inline namespace free_enablement_tests -{ - auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_begin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_free_begin_v)); - } - - auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_begin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_free_begin_v)); - } - - auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_cbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_free_cbegin_v)); - } - - auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_rbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_free_rbegin_v)); - } - - auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_rbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_free_rbegin_v)); - } - - auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_crbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_free_crbegin_v)); - } - - auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_end() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_free_end_v)); - } - - auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_end() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_free_end_v)); - } - - auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_cend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_free_cend_v)); - } - - auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_rend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_free_rend_v)); - } - - auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_rend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_free_rend_v)); - } - - auto a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_crend() -> void - { - using type_alias = nt::new_type; - ASSERT(!(nt::impl::has_free_crend_v)); - } - - auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_begin() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_free_begin_v); - } - - auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_begin() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_free_begin_v); - } - - auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_cbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_free_cbegin_v); - } - - auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_rbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_free_rbegin_v); - } - - auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_rbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_free_rbegin_v); - } - - auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_crbegin() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_free_crbegin_v); - } - - auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_end() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_free_end_v); - } - - auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_end() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_free_end_v); - } - - auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_cend() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_free_cend_v); - } - - auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_rend() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_free_rend_v); - } - - auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_rend() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_free_rend_v); - } - - auto a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_crend() -> void - { - using type_alias = nt::new_type; - ASSERT(nt::impl::has_free_crend_v); - } - -} // namespace free_enablement_tests - -inline namespace semantic_tests -{ - - auto a_non_const_object_of_iterable_new__type_can_be_used_in_value_range_for() -> void - { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto object = type_alias{{1, 2, 3}}; - for (auto e : object) - { - (void)e; - } - ASSERT(true); - } - - auto a_const_object_of_iterable_new__type_can_be_used_in_value_range_for() -> void - { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto const object = type_alias{{1, 2, 3}}; - for (auto e : object) - { - (void)e; - } - ASSERT(true); - } - - auto a_non_const_object_of_iterable_new__type_can_be_used_in_reference_range_for() -> void - { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto object = type_alias{{1, 2, 3}}; - for (auto & e : object) - { - (void)e; - } - ASSERT(true); - } - - auto a_const_object_of_iterable_new__type_can_be_used_in_const_reference_range_for() -> void - { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto const object = type_alias{{1, 2, 3}}; - for (auto const & e : object) - { - (void)e; - } - ASSERT(true); - } - - auto applying_accumulate_to_an_interable_new__type_yields_the_same_result_as_when_applied_to_the_base_type() -> void - { - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto const nt_object = type_alias{{1, 2, 3}}; - auto const bt_object = type_alias::base_type{1, 2, 3}; - - auto nt_result = std::accumulate(std::cbegin(nt_object), std::cend(nt_object), 0); - auto bt_result = std::accumulate(std::cbegin(bt_object), std::cend(bt_object), 0); - - ASSERT_EQUAL(bt_result, nt_result); - } - - auto iterating_over_an_iterable_new__type_yields_the_elements_in_the_same_order_as_when_iterating_the_base_type() -> void - { - using std::cbegin, std::cend, std::equal; - using type_alias = nt::new_type, struct tag, deriving(nt::Iterable)>; - auto const nt_object = type_alias{{1, 2, 3}}; - auto const bt_object = type_alias::base_type{1, 2, 3}; - - ASSERT(equal(cbegin(nt_object), cend(nt_object), cbegin(bt_object), cend(bt_object))); - } - -} // namespace semantic_tests - -auto iterable_suite() -> std::pair -{ - return {{ - /// Combined Enablement Tests - KAWAII(a_new__type_not_deriving_iterable_has_no_begin), - KAWAII(a_new__type_not_deriving_iterable_has_no_constant_begin), - KAWAII(a_new__type_not_deriving_iterable_has_no_cbegin), - KAWAII(a_new__type_not_deriving_iterable_has_no_rbegin), - KAWAII(a_new__type_not_deriving_iterable_has_no_constant_rbegin), - KAWAII(a_new__type_not_deriving_iterable_has_no_crbegin), - KAWAII(a_new__type_not_deriving_iterable_has_no_end), - KAWAII(a_new__type_not_deriving_iterable_has_no_constant_end), - KAWAII(a_new__type_not_deriving_iterable_has_no_cend), - KAWAII(a_new__type_not_deriving_iterable_has_no_rend), - KAWAII(a_new__type_not_deriving_iterable_has_no_constant_rend), - KAWAII(a_new__type_not_deriving_iterable_has_no_crend), - KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_begin), - KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_begin), - KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_cbegin), - KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_rbegin), - KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_rbegin), - KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_crbegin), - KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_end), - KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_end), - KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_cend), - KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_rend), - KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_constant_rend), - KAWAII(a_new__type_on_a_non_iterable_type_deriving_iterable_has_no_crend), - - /// Member Enablement Tests - KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_begin), - KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_begin), - KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_cbegin), - KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_rbegin), - KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_rbegin), - KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_crbegin), - KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_end), - KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_end), - KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_cend), - KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_rend), - KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_constant_rend), - KAWAII(a_new__type_on_a_non_member_iterable_type_deriving_iterable_has_no_member_crend), - KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_begin), - KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_begin), - KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_cbegin), - KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_rbegin), - KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_rbegin), - KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_crbegin), - KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_end), - KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_end), - KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_cend), - KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_rend), - KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_constant_rend), - KAWAII(a_new__type_on_a_member_iterable_type_deriving_iterable_has_member_crend), - - /// Free Enablement Tests - KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_begin), - KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_begin), - KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_cbegin), - KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_rbegin), - KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_rbegin), - KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_crbegin), - KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_end), - KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_end), - KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_cend), - KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_rend), - KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_constant_rend), - KAWAII(a_new__type_on_a_non_free_iterable_type_deriving_iterable_has_no_free_crend), - KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_begin), - KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_begin), - KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_cbegin), - KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_rbegin), - KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_rbegin), - KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_crbegin), - KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_end), - KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_end), - KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_cend), - KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_rend), - KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_constant_rend), - KAWAII(a_new__type_on_a_free_iterable_type_deriving_iterable_has_free_crend), - - /// Semantic Tests - KAWAII(a_non_const_object_of_iterable_new__type_can_be_used_in_value_range_for), - KAWAII(a_const_object_of_iterable_new__type_can_be_used_in_value_range_for), - KAWAII(a_non_const_object_of_iterable_new__type_can_be_used_in_reference_range_for), - KAWAII(a_const_object_of_iterable_new__type_can_be_used_in_const_reference_range_for), - KAWAII(applying_accumulate_to_an_interable_new__type_yields_the_same_result_as_when_applied_to_the_base_type), - KAWAII(iterating_over_an_iterable_new__type_yields_the_elements_