diff options
| author | Martin Hořeňovský | 2026-05-12 08:57:55 +0200 |
|---|---|---|
| committer | Martin Hořeňovský | 2026-05-12 11:05:29 +0200 |
| commit | 3cdae5faf08b7a3861be5e7bf6f1968e9229f460 (patch) | |
| tree | 883148c9b341e24169bce2595da512159450968e | |
| parent | 651247c7f40eda6846fec736d2f9edac8949dacb (diff) | |
| download | catch3-3cdae5faf08b7a3861be5e7bf6f1968e9229f460.tar.gz | |
Constexpr matching support in IsEmpty and SizeIs matchers
| -rw-r--r-- | docs/matchers.md | 9 | ||||
| -rw-r--r-- | src/catch2/matchers/catch_matchers_container_properties.cpp | 8 | ||||
| -rw-r--r-- | src/catch2/matchers/catch_matchers_container_properties.hpp | 18 | ||||
| -rw-r--r-- | tests/SelfTest/UsageTests/MatchersConstexpr.tests.cpp | 12 |
4 files changed, 31 insertions, 16 deletions
diff --git a/docs/matchers.md b/docs/matchers.md index a013245c..a27bbddd 100644 --- a/docs/matchers.md +++ b/docs/matchers.md @@ -491,6 +491,15 @@ TEST_CASE("Constexpr support for matchers", "[constexpr][matchers]") { } ``` +### First party constexpr matchers + +Some (but not all) of Catch2's generic matchers support `constexpr` +matching. Currently, this includes: + +* `IsEmpty()` +* `SizeIs(size_t target_size)` +* `SizeIs(Matcher size_matcher)` + --- diff --git a/src/catch2/matchers/catch_matchers_container_properties.cpp b/src/catch2/matchers/catch_matchers_container_properties.cpp index f0c535bc..6297221e 100644 --- a/src/catch2/matchers/catch_matchers_container_properties.cpp +++ b/src/catch2/matchers/catch_matchers_container_properties.cpp @@ -22,13 +22,5 @@ namespace Matchers { return sstr.str(); } - IsEmptyMatcher IsEmpty() { - return {}; - } - - HasSizeMatcher SizeIs(std::size_t sz) { - return HasSizeMatcher{ sz }; - } - } // end namespace Matchers } // end namespace Catch diff --git a/src/catch2/matchers/catch_matchers_container_properties.hpp b/src/catch2/matchers/catch_matchers_container_properties.hpp index 33795fbe..552bbab1 100644 --- a/src/catch2/matchers/catch_matchers_container_properties.hpp +++ b/src/catch2/matchers/catch_matchers_container_properties.hpp @@ -18,7 +18,7 @@ namespace Catch { class IsEmptyMatcher final : public MatcherGenericBase { public: template <typename RangeLike> - bool match(RangeLike&& rng) const { + constexpr bool match(RangeLike&& rng) const { #if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS) using Catch::Detail::empty; #else @@ -33,12 +33,12 @@ namespace Catch { class HasSizeMatcher final : public MatcherGenericBase { std::size_t m_target_size; public: - explicit HasSizeMatcher(std::size_t target_size): + constexpr explicit HasSizeMatcher(std::size_t target_size): m_target_size(target_size) {} template <typename RangeLike> - bool match(RangeLike&& rng) const { + constexpr bool match(RangeLike&& rng) const { #if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS) using Catch::Detail::size; #else @@ -54,12 +54,12 @@ namespace Catch { class SizeMatchesMatcher final : public MatcherGenericBase { Matcher m_matcher; public: - explicit SizeMatchesMatcher(Matcher m): + constexpr explicit SizeMatchesMatcher(Matcher m): m_matcher(CATCH_MOVE(m)) {} template <typename RangeLike> - bool match(RangeLike&& rng) const { + constexpr bool match(RangeLike&& rng) const { #if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS) using Catch::Detail::size; #else @@ -75,11 +75,13 @@ namespace Catch { //! Creates a matcher that accepts empty ranges/containers - IsEmptyMatcher IsEmpty(); + inline CATCH_DESTRUCTOR_CONSTEXPR IsEmptyMatcher IsEmpty() { return {}; } //! Creates a matcher that accepts ranges/containers with specific size - HasSizeMatcher SizeIs(std::size_t sz); + inline CATCH_DESTRUCTOR_CONSTEXPR HasSizeMatcher SizeIs( std::size_t sz ) { + return HasSizeMatcher{ sz }; + } template <typename Matcher> - std::enable_if_t<Detail::is_matcher_v<Matcher>, + constexpr std::enable_if_t<Detail::is_matcher_v<Matcher>, SizeMatchesMatcher<Matcher>> SizeIs(Matcher&& m) { return SizeMatchesMatcher<Matcher>{CATCH_FORWARD(m)}; } diff --git a/tests/SelfTest/UsageTests/MatchersConstexpr.tests.cpp b/tests/SelfTest/UsageTests/MatchersConstexpr.tests.cpp index edd03519..0d910daf 100644 --- a/tests/SelfTest/UsageTests/MatchersConstexpr.tests.cpp +++ b/tests/SelfTest/UsageTests/MatchersConstexpr.tests.cpp @@ -8,6 +8,9 @@ #include <catch2/catch_test_macros.hpp> #include <catch2/matchers/catch_matchers_templated.hpp> +#include <catch2/matchers/catch_matchers_container_properties.hpp> + +#include <array> #if defined( CATCH_INTERNAL_CONSTEXPR_MATCHERS_ENABLED ) @@ -34,6 +37,15 @@ TEST_CASE( "Constexpr support for matchers", "[constexpr][matchers][approvals]" STATIC_REQUIRE_THAT( 1, MatchAll() ); } +TEST_CASE( "IsEmpty and HasSize matchers can be used in constexpr contexts", + "[constexpr][matchers][approvals]" ){ + static constexpr std::array<int, 0> empty{}; + STATIC_REQUIRE_THAT( empty, Catch::Matchers::IsEmpty() ); + static constexpr int arr[1] = { 2 }; + STATIC_REQUIRE_THAT( arr, Catch::Matchers::SizeIs( 1 ) ); + STATIC_REQUIRE_THAT( arr, Catch::Matchers::SizeIs( MatchAll() ) ); +} + // Combining matchers needs C++26 and P2738, so they are in separate preprocessor block # if __cpp_constexpr >= 202306L |