Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:07

0001 
0002 //              Copyright Catch2 Authors
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //   (See accompanying file LICENSE.txt or copy at
0005 //        https://www.boost.org/LICENSE_1_0.txt)
0006 
0007 // SPDX-License-Identifier: BSL-1.0
0008 #ifndef CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
0009 #define CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
0010 
0011 #include <catch2/matchers/catch_matchers.hpp>
0012 #include <catch2/internal/catch_stringref.hpp>
0013 #include <catch2/internal/catch_move_and_forward.hpp>
0014 #include <catch2/internal/catch_logical_traits.hpp>
0015 
0016 #include <array>
0017 #include <algorithm>
0018 #include <string>
0019 #include <type_traits>
0020 
0021 namespace Catch {
0022 namespace Matchers {
0023     class MatcherGenericBase : public MatcherUntypedBase {
0024     public:
0025         MatcherGenericBase() = default;
0026         ~MatcherGenericBase() override; // = default;
0027 
0028         MatcherGenericBase(MatcherGenericBase const&) = default;
0029         MatcherGenericBase(MatcherGenericBase&&) = default;
0030 
0031         MatcherGenericBase& operator=(MatcherGenericBase const&) = delete;
0032         MatcherGenericBase& operator=(MatcherGenericBase&&) = delete;
0033     };
0034 
0035 
0036     namespace Detail {
0037         template<std::size_t N, std::size_t M>
0038         std::array<void const*, N + M> array_cat(std::array<void const*, N> && lhs, std::array<void const*, M> && rhs) {
0039             std::array<void const*, N + M> arr{};
0040             std::copy_n(lhs.begin(), N, arr.begin());
0041             std::copy_n(rhs.begin(), M, arr.begin() + N);
0042             return arr;
0043         }
0044 
0045         template<std::size_t N>
0046         std::array<void const*, N+1> array_cat(std::array<void const*, N> && lhs, void const* rhs) {
0047             std::array<void const*, N+1> arr{};
0048             std::copy_n(lhs.begin(), N, arr.begin());
0049             arr[N] = rhs;
0050             return arr;
0051         }
0052 
0053         template<std::size_t N>
0054         std::array<void const*, N+1> array_cat(void const* lhs, std::array<void const*, N> && rhs) {
0055             std::array<void const*, N + 1> arr{ {lhs} };
0056             std::copy_n(rhs.begin(), N, arr.begin() + 1);
0057             return arr;
0058         }
0059 
0060         template<typename T>
0061         using is_generic_matcher = std::is_base_of<
0062             Catch::Matchers::MatcherGenericBase,
0063             std::remove_cv_t<std::remove_reference_t<T>>
0064         >;
0065 
0066         template<typename... Ts>
0067         using are_generic_matchers = Catch::Detail::conjunction<is_generic_matcher<Ts>...>;
0068 
0069         template<typename T>
0070         using is_matcher = std::is_base_of<
0071             Catch::Matchers::MatcherUntypedBase,
0072             std::remove_cv_t<std::remove_reference_t<T>>
0073         >;
0074 
0075 
0076         template<std::size_t N, typename Arg>
0077         bool match_all_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
0078             return true;
0079         }
0080 
0081         template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
0082         bool match_all_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
0083             return static_cast<T const*>(matchers[Idx])->match(arg) && match_all_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
0084         }
0085 
0086 
0087         template<std::size_t N, typename Arg>
0088         bool match_any_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
0089             return false;
0090         }
0091 
0092         template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
0093         bool match_any_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
0094             return static_cast<T const*>(matchers[Idx])->match(arg) || match_any_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
0095         }
0096 
0097         std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end);
0098 
0099         template<typename... MatcherTs, std::size_t... Idx>
0100         std::string describe_multi_matcher(StringRef combine, std::array<void const*, sizeof...(MatcherTs)> const& matchers, std::index_sequence<Idx...>) {
0101             std::array<std::string, sizeof...(MatcherTs)> descriptions {{
0102                 static_cast<MatcherTs const*>(matchers[Idx])->toString()...
0103             }};
0104 
0105             return describe_multi_matcher(combine, descriptions.data(), descriptions.data() + descriptions.size());
0106         }
0107 
0108 
0109         template<typename... MatcherTs>
0110         class MatchAllOfGeneric final : public MatcherGenericBase {
0111         public:
0112             MatchAllOfGeneric(MatchAllOfGeneric const&) = delete;
0113             MatchAllOfGeneric& operator=(MatchAllOfGeneric const&) = delete;
0114             MatchAllOfGeneric(MatchAllOfGeneric&&) = default;
0115             MatchAllOfGeneric& operator=(MatchAllOfGeneric&&) = default;
0116 
0117             MatchAllOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {}
0118             explicit MatchAllOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
0119 
0120             template<typename Arg>
0121             bool match(Arg&& arg) const {
0122                 return match_all_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
0123             }
0124 
0125             std::string describe() const override {
0126                 return describe_multi_matcher<MatcherTs...>(" and "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
0127             }
0128 
0129             // Has to be public to enable the concatenating operators
0130             // below, because they are not friend of the RHS, only LHS,
0131             // and thus cannot access private fields of RHS
0132             std::array<void const*, sizeof...( MatcherTs )> m_matchers;
0133 
0134 
0135             //! Avoids type nesting for `GenericAllOf && GenericAllOf` case
0136             template<typename... MatchersRHS>
0137             friend
0138             MatchAllOfGeneric<MatcherTs..., MatchersRHS...> operator && (
0139                     MatchAllOfGeneric<MatcherTs...>&& lhs,
0140                     MatchAllOfGeneric<MatchersRHS...>&& rhs) {
0141                 return MatchAllOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
0142             }
0143 
0144             //! Avoids type nesting for `GenericAllOf && some matcher` case
0145             template<typename MatcherRHS>
0146             friend std::enable_if_t<is_matcher<MatcherRHS>::value,
0147             MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && (
0148                     MatchAllOfGeneric<MatcherTs...>&& lhs,
0149                     MatcherRHS const& rhs) {
0150                 return MatchAllOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(&rhs))};
0151             }
0152 
0153             //! Avoids type nesting for `some matcher && GenericAllOf` case
0154             template<typename MatcherLHS>
0155             friend std::enable_if_t<is_matcher<MatcherLHS>::value,
0156             MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && (
0157                     MatcherLHS const& lhs,
0158                     MatchAllOfGeneric<MatcherTs...>&& rhs) {
0159                 return MatchAllOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))};
0160             }
0161         };
0162 
0163 
0164         template<typename... MatcherTs>
0165         class MatchAnyOfGeneric final : public MatcherGenericBase {
0166         public:
0167             MatchAnyOfGeneric(MatchAnyOfGeneric const&) = delete;
0168             MatchAnyOfGeneric& operator=(MatchAnyOfGeneric const&) = delete;
0169             MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default;
0170             MatchAnyOfGeneric& operator=(MatchAnyOfGeneric&&) = default;
0171 
0172             MatchAnyOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {}
0173             explicit MatchAnyOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
0174 
0175             template<typename Arg>
0176             bool match(Arg&& arg) const {
0177                 return match_any_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
0178             }
0179 
0180             std::string describe() const override {
0181                 return describe_multi_matcher<MatcherTs...>(" or "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
0182             }
0183 
0184 
0185             // Has to be public to enable the concatenating operators
0186             // below, because they are not friend of the RHS, only LHS,
0187             // and thus cannot access private fields of RHS
0188             std::array<void const*, sizeof...( MatcherTs )> m_matchers;
0189 
0190             //! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case
0191             template<typename... MatchersRHS>
0192             friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...> operator || (
0193                     MatchAnyOfGeneric<MatcherTs...>&& lhs,
0194                     MatchAnyOfGeneric<MatchersRHS...>&& rhs) {
0195                 return MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
0196             }
0197 
0198             //! Avoids type nesting for `GenericAnyOf || some matcher` case
0199             template<typename MatcherRHS>
0200             friend std::enable_if_t<is_matcher<MatcherRHS>::value,
0201             MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || (
0202                     MatchAnyOfGeneric<MatcherTs...>&& lhs,
0203                     MatcherRHS const& rhs) {
0204                 return MatchAnyOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))};
0205             }
0206 
0207             //! Avoids type nesting for `some matcher || GenericAnyOf` case
0208             template<typename MatcherLHS>
0209             friend std::enable_if_t<is_matcher<MatcherLHS>::value,
0210             MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || (
0211                 MatcherLHS const& lhs,
0212                 MatchAnyOfGeneric<MatcherTs...>&& rhs) {
0213                 return MatchAnyOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))};
0214             }
0215         };
0216 
0217 
0218         template<typename MatcherT>
0219         class MatchNotOfGeneric final : public MatcherGenericBase {
0220             MatcherT const& m_matcher;
0221 
0222         public:
0223             MatchNotOfGeneric(MatchNotOfGeneric const&) = delete;
0224             MatchNotOfGeneric& operator=(MatchNotOfGeneric const&) = delete;
0225             MatchNotOfGeneric(MatchNotOfGeneric&&) = default;
0226             MatchNotOfGeneric& operator=(MatchNotOfGeneric&&) = default;
0227 
0228             explicit MatchNotOfGeneric(MatcherT const& matcher) : m_matcher{matcher} {}
0229 
0230             template<typename Arg>
0231             bool match(Arg&& arg) const {
0232                 return !m_matcher.match(arg);
0233             }
0234 
0235             std::string describe() const override {
0236                 return "not " + m_matcher.toString();
0237             }
0238 
0239             //! Negating negation can just unwrap and return underlying matcher
0240             friend MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) {
0241                 return matcher.m_matcher;
0242             }
0243         };
0244     } // namespace Detail
0245 
0246 
0247     // compose only generic matchers
0248     template<typename MatcherLHS, typename MatcherRHS>
0249     std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>>
0250         operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) {
0251         return { lhs, rhs };
0252     }
0253 
0254     template<typename MatcherLHS, typename MatcherRHS>
0255     std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>
0256         operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) {
0257         return { lhs, rhs };
0258     }
0259 
0260     //! Wrap provided generic matcher in generic negator
0261     template<typename MatcherT>
0262     std::enable_if_t<Detail::is_generic_matcher<MatcherT>::value, Detail::MatchNotOfGeneric<MatcherT>>
0263         operator ! (MatcherT const& matcher) {
0264         return Detail::MatchNotOfGeneric<MatcherT>{matcher};
0265     }
0266 
0267 
0268     // compose mixed generic and non-generic matchers
0269     template<typename MatcherLHS, typename ArgRHS>
0270     std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
0271         operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
0272         return { lhs, rhs };
0273     }
0274 
0275     template<typename ArgLHS, typename MatcherRHS>
0276     std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
0277         operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
0278         return { lhs, rhs };
0279     }
0280 
0281     template<typename MatcherLHS, typename ArgRHS>
0282     std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
0283         operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
0284         return { lhs, rhs };
0285     }
0286 
0287     template<typename ArgLHS, typename MatcherRHS>
0288     std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
0289         operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
0290         return { lhs, rhs };
0291     }
0292 
0293 } // namespace Matchers
0294 } // namespace Catch
0295 
0296 #endif // CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED