diff options
| author | Leitwolf11 | 2026-09-29 19:54:42 +0300 |
|---|---|---|
| committer | Leitwolf11 | 2026-09-29 19:54:42 +0300 |
| commit | a870d0a4b37c2840db4eeaaaaf57b4eab4db75d3 (patch) | |
| tree | 4de83fbe2df34f34160b2dad2a60147bb2a0b1be /src/Progmasoft/Catch3/Generators | |
| parent | 1f2ec07fdfe05af6df9a573f2c16551e91eef3a6 (diff) | |
| download | catch3-a870d0a4b37c2840db4eeaaaaf57b4eab4db75d3.tar.gz | |
Support exception-free clients in Catch3 property headers
Preserve the existing exception-throwing and exception-catching API when language exceptions are enabled. Compile the property evaluator, shrinker and value formatter without try/catch for clients using -fno-exceptions, and fail loudly on invalid generator range or missing callbacks instead of requiring throw expressions in those translation units.
Export the new diagnostic helper through Bazel and Meson header installations. This changes neither the upstream Catch2 implementation nor its compiler flags.
Validation: Clang++ C++20 syntax checks passed for property generators with exceptions both disabled and enabled; changed headers were formatted and git diff --check passed. The consuming compiler's Linux/Windows/macOS CI will verify the integration.
Diffstat (limited to 'src/Progmasoft/Catch3/Generators')
| -rw-r--r-- | src/Progmasoft/Catch3/Generators/Integer.hpp | 108 |
1 files changed, 68 insertions, 40 deletions
diff --git a/src/Progmasoft/Catch3/Generators/Integer.hpp b/src/Progmasoft/Catch3/Generators/Integer.hpp index 2a50525e..45192b3d 100644 --- a/src/Progmasoft/Catch3/Generators/Integer.hpp +++ b/src/Progmasoft/Catch3/Generators/Integer.hpp @@ -3,55 +3,81 @@ #pragma once #include <Progmasoft/Catch3/Generator.hpp> - #include <algorithm> #include <concepts> #include <limits> #include <type_traits> -namespace Progmasoft::Catch3 { - namespace Detail { +namespace Progmasoft::Catch3 +{ + namespace Detail + { - template <std::integral IntegerType> - requires( !std::same_as<IntegerType, bool> ) - [[nodiscard]] std::vector<IntegerType> ShrinkInteger( - IntegerType value, IntegerType minimum, IntegerType maximum ) { + template<std::integral IntegerType> + requires(!std::same_as<IntegerType, bool>) + [[nodiscard]] std::vector<IntegerType> + ShrinkInteger(IntegerType value, + IntegerType minimum, + IntegerType maximum) + { std::vector<IntegerType> candidates; - const auto addCandidate = [&]( IntegerType candidate ) { - if ( candidate < minimum || candidate > maximum || - candidate == value || - std::ranges::find( candidates, candidate ) != - candidates.end() ) { + const auto addCandidate = [&](IntegerType candidate) { + if (candidate < minimum || candidate > maximum + || candidate == value + || std::ranges::find(candidates, candidate) + != candidates.end()) + { return; } - candidates.push_back( candidate ); + candidates.push_back(candidate); }; - if ( value == 0 ) { return candidates; } + if (value == 0) + { + return candidates; + } // First try the conventional simplest value, then halve toward it. // The adjacent value at the end lets the runner find boundary // counterexamples (for example, the first failing integer in a // threshold property). - if ( minimum <= 0 && maximum >= 0 ) { addCandidate( 0 ); } + if (minimum <= 0 && maximum >= 0) + { + addCandidate(0); + } IntegerType smaller = value; - while ( smaller != 0 ) { - smaller = static_cast<IntegerType>( smaller / 2 ); - if ( smaller == 0 ) { break; } - addCandidate( smaller ); + while (smaller != 0) + { + smaller = static_cast<IntegerType>(smaller / 2); + if (smaller == 0) + { + break; + } + addCandidate(smaller); } - if ( value > 0 ) { - if ( value > minimum ) { - addCandidate( static_cast<IntegerType>( value - 1 ) ); + if (value > 0) + { + if (value > minimum) + { + addCandidate(static_cast<IntegerType>(value - 1)); + } + if (minimum > 0) + { + addCandidate(minimum); + } + } + else + { + if (value < maximum) + { + addCandidate(static_cast<IntegerType>(value + 1)); } - if ( minimum > 0 ) { addCandidate( minimum ); } - } else { - if ( value < maximum ) { - addCandidate( static_cast<IntegerType>( value + 1 ) ); + if (maximum < 0) + { + addCandidate(maximum); } - if ( maximum < 0 ) { addCandidate( maximum ); } } return candidates; } @@ -60,23 +86,25 @@ namespace Progmasoft::Catch3 { /// Generates integers over the inclusive range and shrinks toward simple /// values. - template <std::integral IntegerType> - requires( !std::same_as<IntegerType, bool> ) - [[nodiscard]] Generator<IntegerType> Integer( - IntegerType minimum = std::numeric_limits<IntegerType>::lowest(), - IntegerType maximum = std::numeric_limits<IntegerType>::max() ) { - if ( minimum > maximum ) { - throw std::invalid_argument( - "Integer requires minimum <= maximum" ); + template<std::integral IntegerType> + requires(!std::same_as<IntegerType, bool>) + [[nodiscard]] Generator<IntegerType> + Integer(IntegerType minimum = std::numeric_limits<IntegerType>::lowest(), + IntegerType maximum = std::numeric_limits<IntegerType>::max()) + { + if (minimum > maximum) + { + Detail::RejectInvalidArgument( + "Integer requires minimum <= maximum"); } return MakeGenerator<IntegerType>( - [minimum, maximum]( Random& random ) { - return random.Between( minimum, maximum ); + [minimum, maximum](Random &random) { + return random.Between(minimum, maximum); }, - [minimum, maximum]( const IntegerType& value ) { - return Detail::ShrinkInteger( value, minimum, maximum ); - } ); + [minimum, maximum](const IntegerType &value) { + return Detail::ShrinkInteger(value, minimum, maximum); + }); } } // namespace Progmasoft::Catch3 |