Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorLeitwolf112026-10-23 02:33:21 +0300
committerLeitwolf112026-10-23 02:33:21 +0300
commitc7e625419e699f139c15ae190b0169d93768abe7 (patch)
treef39027814c87061e8f3ff9cc269945e1219372e2 /src
parentafac14ac5a62d8d2e7efd2184ad34e16593eddfd (diff)
downloadcatch3-c7e625419e699f139c15ae190b0169d93768abe7.tar.gz
Draw tuples without capturing a pack in a nested lambda
MSVC rejected Gen::Tuples with C3493: the strategies were captured as a parameter pack and used inside a nested std::apply lambda. The strategies are now held as one std::tuple and drawn by Detail::DrawTuple over an index sequence; the comma fold still draws them strictly left to right, so choice sequences do not change. Verified: ProgmasoftSelfTest passes with MSVC 19.51 (cl) and with clang-cl 23, 57 test cases and 75,461 assertions each. The macOS and CodeQL failures of the previous run were runners that never started.
Diffstat (limited to 'src')
-rw-r--r--src/Progmasoft/Catch3/Strategy/Containers.hpp56
1 files changed, 32 insertions, 24 deletions
diff --git a/src/Progmasoft/Catch3/Strategy/Containers.hpp b/src/Progmasoft/Catch3/Strategy/Containers.hpp
index 477df896..ad4daf39 100644
--- a/src/Progmasoft/Catch3/Strategy/Containers.hpp
+++ b/src/Progmasoft/Catch3/Strategy/Containers.hpp
@@ -61,6 +61,30 @@ namespace Progmasoft::Catch3
return true;
}
+ /// Draws one value from each strategy, strictly left to right: the
+ /// fold over the comma operator fixes the order, which keeps the
+ /// choice sequence of a tuple stable.
+ template<typename... ValueTypes, std::size_t... Index>
+ [[nodiscard]] std::optional<std::tuple<ValueTypes...>>
+ DrawTuple(const std::tuple<Strategy<ValueTypes>...> &strategies,
+ ChoiceSource &source,
+ std::index_sequence<Index...>)
+ {
+ std::tuple<std::optional<ValueTypes>...> parts;
+ bool complete = true;
+ ((complete = complete
+ && (std::get<Index>(parts)
+ = std::get<Index>(strategies).Draw(source))
+ .has_value()),
+ ...);
+ if (!complete)
+ {
+ return std::nullopt;
+ }
+ return std::tuple<ValueTypes...>(
+ std::move(*std::get<Index>(parts))...);
+ }
+
inline void
CheckRange(const SizeRange &range)
{
@@ -320,31 +344,15 @@ namespace Progmasoft::Catch3
[[nodiscard]] Strategy<std::tuple<ValueTypes...>>
Tuples(Strategy<ValueTypes>... strategies)
{
+ // The strategies are held as one tuple rather than captured as
+ // a pack: MSVC rejects a pack used inside a nested lambda.
return Strategy<std::tuple<ValueTypes...>>(
- [strategies...](ChoiceSource &source)
- -> std::optional<std::tuple<ValueTypes...>> {
- std::tuple<std::optional<ValueTypes>...> parts;
- bool complete = true;
- // A braced list fixes the evaluation order: left to
- // right, which keeps the choice sequence stable.
- std::apply(
- [&](auto &...part) {
- ((complete = complete
- && (part = strategies.Draw(source))
- .has_value()),
- ...);
- },
- parts);
- if (!complete)
- {
- return std::nullopt;
- }
- return std::apply(
- [](auto &...part) {
- return std::tuple<ValueTypes...>(
- std::move(*part)...);
- },
- parts);
+ [strategies = std::tuple<Strategy<ValueTypes>...>(
+ std::move(strategies)...)](ChoiceSource &source) {
+ return Detail::DrawTuple(
+ strategies,
+ source,
+ std::index_sequence_for<ValueTypes...>{});
});
}