diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2020-02-28 06:46:26 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2020-02-28 06:46:26 +0100 |
| commit | b01d495beb586d8d18ef592d80f593ea1bbe10e2 (patch) | |
| tree | 12e56ffcc2c517a1d834c97915cbf007037692ff | |
| parent | dc369b4c559b33868ffdb99eb4a2feadd90a84f2 (diff) | |
| download | newtype-b01d495beb586d8d18ef592d80f593ea1bbe10e2.tar.xz newtype-b01d495beb586d8d18ef592d80f593ea1bbe10e2.zip | |
new_type: implement rbegin and crbegin
| -rw-r--r-- | doc/src/index.rst | 99 | ||||
| -rw-r--r-- | include/newtype/impl/new_type_iterator_types.hpp | 24 | ||||
| -rw-r--r-- | include/newtype/impl/type_traits_extensions.hpp | 90 | ||||
| -rw-r--r-- | include/newtype/new_type.hpp | 62 | ||||
| -rw-r--r-- | test/src/iterable_suite.cpp | 136 |
5 files changed, 409 insertions, 2 deletions
diff --git a/doc/src/index.rst b/doc/src/index.rst index cd016b9..a54d54c 100644 --- a/doc/src/index.rst +++ b/doc/src/index.rst @@ -99,6 +99,18 @@ Class template :cpp:class:`new_type` .. versionadded:: 1.1.0 + .. cpp:type:: reverse_iterator = typename BaseType::reverse_iterator + + :enablement: This type alias shall be defined iff. this :cpp:class:`new_type`'s :cpp:type:`base_type` has a member type :cpp:type:`reverse_iterator <new_type::base_type::reverse_iterator>` and the :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable`. + + .. versionadded:: 1.1.0 + + .. cpp:type:: const_reverse_iterator = typename BaseType::const_reverse_iterator + + :enablement: This type alias shall be defined iff. this :cpp:class:`new_type`'s :cpp:type:`base_type` has a member type :cpp:type:`const_reverse_iterator <new_type::base_type::const_reverse_iterator>` and the :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable`. + + .. versionadded:: 1.1.0 + **Static Data Members** .. cpp:var:: static derivation_clause_type constexpr derivation_clause = DerivationClause @@ -242,6 +254,39 @@ Class template :cpp:class:`new_type` .. versionadded:: 1.1.0 + .. cpp:function:: constexpr iterator rbegin() + + Get a reverse iterator to the beginning of the object contained by this :cpp:class:`new_type` + + :enablement: This function shall be available iff. + + a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and + b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`rbegin() <new_type::base_type::rbegin()>` that returns an instance of type :cpp:type:`reverse_iterator` + + .. versionadded:: 1.1.0 + + .. cpp:function:: constexpr iterator rbegin() const + + Get a constant reverse iterator to the beginning of the object contained by this :cpp:class:`new_type` + + :enablement: This function shall be available iff. + + a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and + b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`rbegin() const <new_type::base_type::rbegin()>` that returns an instance of type :cpp:type:`const_reverse_iterator` + + .. versionadded:: 1.1.0 + + .. cpp:function:: constexpr iterator crbegin() const + + Get a constant reverse iterator to the beginning of the object contained by this :cpp:class:`new_type` + + :enablement: This function shall be available iff. + + a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <derivation_clause>` contains :cpp:var:`Iterable` and + b) this :cpp:class:`new_type`'s :cpp:type:`base type <base_type>` has a non-static member function :cpp:func:`crbegin() const <new_type::base_type::crbegin()>` that returns an instance of type :cpp:type:`const_reverse_iterator` + + .. versionadded:: 1.1.0 + :literal:`namespace`-level functions and function templates ----------------------------------------------------------- @@ -750,6 +795,60 @@ Iterators .. versionadded:: 1.1.0 +.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \ + constexpr new_type<BaseType, TagType, DerivationClause>::reverse_iterator rbegin(new_type<BaseType, TagType, DerivationClause> & obj) + + Get a reverse iterator to the beginning of the object contained by an instance of :cpp:class:`new_type` + + :tparam BaseType: |BaseTypeDoc| + :tparam TagType: |TagTypeDoc| + :tparam DerivationClause: |DerivationClauseDoc| + :param obj: The object to retrieve the iterator from + :returns: An iterator to the begining of the object of contained by :literal:`obj`. + :throws: Any exception + :enablement: This function shall be available iff. + + a) :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and + b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`rbegin(BaseType &)` that returns an instance of type :cpp:type:`new_type::reverse_iterator` + + .. versionadded:: 1.1.0 + +.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \ + constexpr new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator rbegin(new_type<BaseType, TagType, DerivationClause> const & obj) + + Get a constant reverse iterator to the beginning of the object contained by an instance of :cpp:class:`new_type` + + :tparam BaseType: |BaseTypeDoc| + :tparam TagType: |TagTypeDoc| + :tparam DerivationClause: |DerivationClauseDoc| + :param obj: The object to retrieve the iterator from + :returns: An iterator to the begining of the object of contained by :cpp:var:`obj`. + :throws: Any exception + :enablement: This function shall be available iff. + + a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and + b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`rbegin(BaseType const &)` that returns an instance of type :cpp:type:`new_type::const_reverse_iterator` + + .. versionadded:: 1.1.0 + +.. cpp:function:: template<typename BaseType, typename TagType, auto DerivationClause> \ + constexpr new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator crbegin(new_type<BaseType, TagType, DerivationClause> const & obj) + + Get a constant reverse iterator to the beginning of the object contained by an instance of :cpp:class:`new_type` + + :tparam BaseType: |BaseTypeDoc| + :tparam TagType: |TagTypeDoc| + :tparam DerivationClause: |DerivationClauseDoc| + :param obj: The object to retrieve the iterator from + :returns: An iterator to the begining of the object of contained by :cpp:var:`obj`. + :throws: Any exception + :enablement: This function shall be available iff. + + a) this :cpp:class:`new_type`'s :cpp:var:`derivation clause <DerivationClause>` contains :cpp:var:`Iterable` and + b) for the :cpp:class:`new_type`'s :cpp:type:`base type <BaseType>` exists a namespace-level function :literal:`crbegin(BaseType const &)` that returns an instance of type :cpp:type:`new_type::const_reverse_iterator` + + .. versionadded:: 1.1.0 + :cpp:class:`std::hash` Support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/include/newtype/impl/new_type_iterator_types.hpp b/include/newtype/impl/new_type_iterator_types.hpp index 037f08d..2ea8274 100644 --- a/include/newtype/impl/new_type_iterator_types.hpp +++ b/include/newtype/impl/new_type_iterator_types.hpp @@ -30,10 +30,34 @@ namespace nt::impl using const_iterator = typename T::const_iterator; }; + template<typename T, bool = false, typename = std::void_t<>> + struct new_type_reverse_iterator + { + }; + + template<typename T> + struct new_type_reverse_iterator<T, true, std::void_t<typename T::reverse_iterator>> + { + using reverse_iterator = typename T::reverse_iterator; + }; + + template<typename T, bool = false, typename = std::void_t<>> + struct new_type_const_reverse_iterator + { + }; + + template<typename T> + struct new_type_const_reverse_iterator<T, true, std::void_t<typename T::const_reverse_iterator>> + { + using const_reverse_iterator = typename T::const_reverse_iterator; + }; + template<typename T, bool Enabled> struct new_type_iterator_types : new_type_iterator<T, Enabled> , new_type_const_iterator<T, Enabled> + , new_type_reverse_iterator<T, Enabled> + , new_type_const_reverse_iterator<T, Enabled> { }; diff --git a/include/newtype/impl/type_traits_extensions.hpp b/include/newtype/impl/type_traits_extensions.hpp index a9bd6af..f7dafef 100644 --- a/include/newtype/impl/type_traits_extensions.hpp +++ b/include/newtype/impl/type_traits_extensions.hpp @@ -578,6 +578,96 @@ namespace nt::impl auto constexpr has_cbegin_v = has_cbegin<T>::value; } // namespace iterable_cbegin + inline namespace iterable_rbegin + { + template<typename T, typename = void> + struct has_free_rbegin : std::false_type + { + }; + + template<typename T> + struct has_free_rbegin<T, std::void_t<decltype(rbegin(std::declval<T &>()))>> + : std::is_same<typename T::reverse_iterator, std::remove_cvref_t<decltype(begin(std::declval<T &>()))>> + { + }; + + template<typename T> + struct has_free_rbegin<T const, std::void_t<decltype(rbegin(std::declval<T const &>()))>> + : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(rbegin(std::declval<T const &>()))>> + { + }; + + template<typename T> + auto constexpr has_free_rbegin_v = has_free_rbegin<T>::value; + + template<typename T, typename = void> + struct has_member_rbegin : std::false_type + { + }; + + template<typename T> + struct has_member_rbegin<T, std::void_t<decltype(std::declval<T &>().rbegin())>> + : std::is_same<typename T::reverse_iterator, std::remove_cvref_t<decltype(std::declval<T &>().rbegin())>> + { + }; + + template<typename T> + struct has_member_rbegin<T const, std::void_t<decltype(std::declval<T const &>().rbegin())>> + : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().rbegin())>> + { + }; + + template<typename T> + auto constexpr has_member_rbegin_v = has_member_rbegin<T>::value; + + template<typename T> + struct has_rbegin : std::disjunction<has_free_rbegin<T>, has_member_rbegin<T>> + { + }; + + template<typename T> + auto constexpr has_rbegin_v = has_rbegin<T>::value; + } // namespace iterable_rbegin + + inline namespace iterable_rbegin + { + template<typename T, typename = void> + struct has_free_crbegin : std::false_type + { + }; + + template<typename T> + struct has_free_crbegin<T, std::void_t<decltype(crbegin(std::declval<T const &>()))>> + : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(crbegin(std::declval<T const &>()))>> + { + }; + + template<typename T> + auto constexpr has_free_crbegin_v = has_free_crbegin<T>::value; + + template<typename T, typename = void> + struct has_member_crbegin : std::false_type + { + }; + + template<typename T> + struct has_member_crbegin<T, std::void_t<decltype(std::declval<T const &>().crbegin())>> + : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().crbegin())>> + { + }; + + template<typename T> + auto constexpr has_member_crbegin_v = has_member_crbegin<T>::value; + + template<typename T> + struct has_crbegin : std::disjunction<has_free_crbegin<T>, has_member_crbegin<T>> + { + }; + + template<typename T> + auto constexpr has_crbegin_v = has_crbegin<T>::value; + } // namespace iterable_rbegin + } // namespace nt::impl #endif
\ No newline at end of file diff --git a/include/newtype/new_type.hpp b/include/newtype/new_type.hpp index 24ac71a..36a3927 100644 --- a/include/newtype/new_type.hpp +++ b/include/newtype/new_type.hpp @@ -65,7 +65,7 @@ namespace nt template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> auto constexpr friend begin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) - -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_begin_v<BaseTypeT>, + -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_begin_v<BaseTypeT const>, typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator>; template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> @@ -73,6 +73,21 @@ namespace nt -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_cbegin_v<BaseTypeT const>, typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator>; + template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + auto constexpr friend rbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj) + -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_rbegin_v<BaseTypeT>, + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::reverse_iterator>; + + template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + auto constexpr friend rbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) + -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_rbegin_v<BaseTypeT const>, + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator>; + + template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + auto constexpr friend crbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) + -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_crbegin_v<BaseTypeT const>, + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator>; + using super = impl::new_type_move_assignment<BaseType, TagType>; public: @@ -140,6 +155,27 @@ namespace nt { return this->m_value.cbegin(); } + + template<typename NewType = new_type, std::enable_if_t<NewType::derivation_clause(nt::Iterable)> * = nullptr> + auto constexpr rbegin() + -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_rbegin_v<BaseType>, typename NewType::reverse_iterator> + { + return this->m_value.rbegin(); + } + + template<typename NewType = new_type> + auto constexpr rbegin() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_rbegin_v<BaseType const>, + typename NewType::const_reverse_iterator> + { + return this->m_value.rbegin(); + } + + template<typename NewType = new_type> + auto constexpr crbegin() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_crbegin_v<BaseType const>, + typename NewType::const_reverse_iterator> + { + return this->m_value.crbegin(); + } }; template<typename BaseType, typename TagType, auto DerivationClause> @@ -350,6 +386,30 @@ namespace nt return cbegin(obj.m_value); } + template<typename BaseType, typename TagType, auto DerivationClause> + auto constexpr rbegin(new_type<BaseType, TagType, DerivationClause> & obj) + -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_rbegin_v<BaseType>, + typename new_type<BaseType, TagType, DerivationClause>::reverse_iterator> + { + return rbegin(obj.m_value); + } + + template<typename BaseType, typename TagType, auto DerivationClause> + auto constexpr rbegin(new_type<BaseType, TagType, DerivationClause> const & obj) + -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_rbegin_v<BaseType const>, + typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator> + { + return rbegin(obj.m_value); + } + + template<typename BaseType, typename TagType, auto DerivationClause> + auto constexpr crbegin(new_type<BaseType, TagType, DerivationClause> const & obj) + -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_crbegin_v<BaseType const>, + typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator> + { + return crbegin(obj.m_value); + } + } // namespace nt namespace std diff --git a/test/src/iterable_suite.cpp b/test/src/iterable_suite.cpp index 3bdb16b..778dc35 100644 --- a/test/src/iterable_suite.cpp +++ b/test/src/iterable_suite.cpp @@ -18,10 +18,15 @@ namespace { using iterator = void *; using const_iterator = void const *; + using reverse_iterator = void *; + using const_reverse_iterator = void const *; 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; }; } // namespace @@ -135,6 +140,117 @@ inline namespace cbegin_tests } // namespace cbegin_tests +inline namespace rbegin_tests +{ + + auto a_new__type_not_deriving_iterable_has_no_rbegin() -> void + { + using type_alias = nt::new_type<int, struct tag>; + ASSERT(!(nt::impl::has_rbegin_v<type_alias>)); + } + + auto a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_rbegin() -> void + { + static_assert(!nt::impl::has_rbegin_v<int>); + using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>; + ASSERT(!(nt::impl::has_rbegin_v<type_alias>)); + } + + auto a_new__type_based_on_an_iterable_type_with_member_rbegin_deriving_iterable_has_member_rbegin() -> void + { + static_assert(nt::impl::has_member_rbegin_v<with_member>); + using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>; + ASSERT(nt::impl::has_member_rbegin_v<type_alias>); + } + + auto a_new__type_based_on_an_iterable_type_with_constant_member_rbegin_deriving_iterable_has_constant_member_rbegin() -> void + { + static_assert(nt::impl::has_member_rbegin_v<with_member const>); + using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>; + ASSERT(nt::impl::has_member_rbegin_v<type_alias const>); + } + + auto a_new__type_based_on_an_iterable_type_without_free_rbegin_deriving_iterable_has_no_free_rbegin() -> void + { + static_assert(!nt::impl::has_free_rbegin_v<with_member>); + using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>; + ASSERT(!nt::impl::has_free_rbegin_v<type_alias>); + } + + auto a_new__type_based_on_an_iterable_type_without_constant_free_rbegin_deriving_iterable_has_no_constant_free_rbegin() -> void + { + static_assert(!nt::impl::has_free_rbegin_v<with_member const>); + using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>; + ASSERT(!nt::impl::has_free_rbegin_v<type_alias const>); + } + + auto accessing_the_first_element_of_a_reverse_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type() + -> void + { + using type_alias = nt::new_type<std::array<int, 3>, struct tag, deriving(nt::Iterable)>; + auto weak = std::array{42, 21, 10}; + auto strong = type_alias{{42, 21, 10}}; + ASSERT_EQUAL(*weak.rbegin(), *strong.rbegin()); + } + + auto an_iterator_obtained_via_member_rbegin_compares_equal_to_an_iterator_obtained_via_free_rbegin() -> void + { + using type_alias = nt::new_type<std::array<int, 3>, struct tag, deriving(nt::Iterable)>; + auto instance = type_alias{{42, 21, 10}}; + ASSERT_EQUAL(rbegin(instance), instance.rbegin()); + } + +} // namespace rbegin_tests + +inline namespace crbegin_tests +{ + + auto a_new__type_not_deriving_iterable_has_no_crbegin() -> void + { + using type_alias = nt::new_type<int, struct tag>; + ASSERT(!(nt::impl::has_crbegin_v<type_alias>)); + } + + auto a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_crbegin() -> void + { + static_assert(!nt::impl::has_crbegin_v<int>); + using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>; + ASSERT(!(nt::impl::has_crbegin_v<type_alias>)); + } + + auto a_new__type_based_on_an_iterable_type_with_member_crbegin_deriving_iterable_has_member_crbegin() -> void + { + static_assert(nt::impl::has_member_crbegin_v<with_member>); + using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>; + ASSERT(nt::impl::has_member_crbegin_v<type_alias>); + } + + auto a_new__type_based_on_an_iterable_type_without_free_crbegin_deriving_iterable_has_no_free_crbegin() -> void + { + static_assert(!nt::impl::has_free_crbegin_v<with_member>); + using type_alias = nt::new_type<with_member, struct tag, deriving(nt::Iterable)>; + ASSERT(!nt::impl::has_free_crbegin_v<type_alias>); + } + + auto + accessing_the_first_element_of_a_constant_reverse_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type() + -> void + { + using type_alias = nt::new_type<std::array<int, 3>, struct tag, deriving(nt::Iterable)>; + auto weak = std::array{42, 21, 10}; + auto strong = type_alias{{42, 21, 10}}; + ASSERT_EQUAL(*weak.crbegin(), *strong.crbegin()); + } + + auto an_iterator_obtained_via_member_crbegin_compares_equal_to_an_iterator_obtained_via_free_crbegin() -> void + { + using type_alias = nt::new_type<std::array<int, 3>, struct tag, deriving(nt::Iterable)>; + auto instance = type_alias{{42, 21, 10}}; + ASSERT_EQUAL(crbegin(instance), instance.crbegin()); + } + +} // namespace crbegin_tests + auto iterable_suite() -> std::pair<cute::suite, std::string> { return { @@ -150,13 +266,31 @@ auto iterable_suite() -> std::pair<cute::suite, std::string> KAWAII(accessing_the_first_element_of_an_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type), KAWAII(an_iterator_obtained_via_member_begin_compares_equal_to_an_iterator_obtained_via_free_begin), - /// 'begin' Tests + /// 'cbegin' Tests KAWAII(a_new__type_not_deriving_iterable_has_no_cbegin), KAWAII(a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_cbegin), KAWAII(a_new__type_based_on_an_iterable_type_with_member_cbegin_deriving_iterable_has_member_cbegin), KAWAII(a_new__type_based_on_an_iterable_type_without_free_cbegin_deriving_iterable_has_no_free_cbegin), KAWAII(accessing_the_first_element_of_a_constant_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type), KAWAII(an_iterator_obtained_via_member_cbegin_compares_equal_to_an_iterator_obtained_via_free_cbegin), + + /// 'rbegin' Tests + KAWAII(a_new__type_not_deriving_iterable_has_no_rbegin), + KAWAII(a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_rbegin), + KAWAII(a_new__type_based_on_an_iterable_type_with_member_rbegin_deriving_iterable_has_member_rbegin), + KAWAII(a_new__type_based_on_an_iterable_type_with_constant_member_rbegin_deriving_iterable_has_constant_member_rbegin), + KAWAII(a_new__type_based_on_an_iterable_type_without_free_rbegin_deriving_iterable_has_no_free_rbegin), + KAWAII(a_new__type_based_on_an_iterable_type_without_constant_free_rbegin_deriving_iterable_has_no_constant_free_rbegin), + KAWAII(accessing_the_first_element_of_a_reverse_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type), + KAWAII(an_iterator_obtained_via_member_rbegin_compares_equal_to_an_iterator_obtained_via_free_rbegin), + + /// 'cbegin' Tests + KAWAII(a_new__type_not_deriving_iterable_has_no_crbegin), + KAWAII(a_new__type_based_on_a_non_iterable_type_deriving_iterable_has_no_crbegin), + KAWAII(a_new__type_based_on_an_iterable_type_with_member_crbegin_deriving_iterable_has_member_crbegin), + KAWAII(a_new__type_based_on_an_iterable_type_without_free_crbegin_deriving_iterable_has_no_free_crbegin), + KAWAII(accessing_the_first_element_of_a_constant_reverse_iterator_on_a_new__type_yields_the_same_value_as_accessing_it_through_an_unwrapped_type), + KAWAII(an_iterator_obtained_via_member_crbegin_compares_equal_to_an_iterator_obtained_via_free_crbegin), // clang-format on }, "Iterable Tests"}; |
