From 54089c4c8c657ffb13d8f3a1425403335af5ba4d Mon Sep 17 00:00:00 2001 From: Omer Ozarslan Date: Sun, 24 Mar 2019 09:44:22 -0500 Subject: [PATCH] Deducing return type of map generator helper (#1576) * Deduce map return type implicitly Giving the first template argument to map generator function to deduce return type is now optional even if the return type is different from the type generated by mapped generator. --- docs/generators.md | 2 +- include/internal/catch_generators_generic.hpp | 20 +++- .../Baselines/compact.sw.approved.txt | 9 ++ .../Baselines/console.std.approved.txt | 2 +- .../Baselines/console.sw.approved.txt | 80 ++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 6 +- .../SelfTest/Baselines/xml.sw.approved.txt | 99 ++++++++++++++++++- .../GeneratorsImpl.tests.cpp | 11 ++- .../SelfTest/UsageTests/Generators.tests.cpp | 5 + 9 files changed, 220 insertions(+), 14 deletions(-) diff --git a/docs/generators.md b/docs/generators.md index da6e5a03..5881a11e 100644 --- a/docs/generators.md +++ b/docs/generators.md @@ -57,7 +57,7 @@ type, making their usage much nicer. These are * `filter(predicate, GeneratorWrapper&&)` for `FilterGenerator` * `take(count, GeneratorWrapper&&)` for `TakeGenerator` * `repeat(repeats, GeneratorWrapper&&)` for `RepeatGenerator` -* `map(func, GeneratorWrapper&&)` for `MapGenerator` (map `T` to `T`) +* `map(func, GeneratorWrapper&&)` for `MapGenerator` (map `U` to `T`, deduced from `Func`) * `map(func, GeneratorWrapper&&)` for `MapGenerator` (map `U` to `T`) * `chunk(chunk-size, GeneratorWrapper&&)` for `ChunkGenerator` * `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator` diff --git a/include/internal/catch_generators_generic.hpp b/include/internal/catch_generators_generic.hpp index 2226dbc5..2903ba69 100644 --- a/include/internal/catch_generators_generic.hpp +++ b/include/internal/catch_generators_generic.hpp @@ -169,16 +169,28 @@ namespace Generators { } }; - template +#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 + // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is + // replaced with std::invoke_result here. Also *_t format is preferred over + // typename *::type format. + template + using MapFunctionReturnType = std::remove_reference_t>>; +#else + template + using MapFunctionReturnType = typename std::remove_reference::type>::type>::type; +#endif + + template > GeneratorWrapper map(Func&& function, GeneratorWrapper&& generator) { return GeneratorWrapper( pf::make_unique>(std::forward(function), std::move(generator)) ); } - template - GeneratorWrapper map(Func&& function, GeneratorWrapper&& generator) { + + template + GeneratorWrapper map(Func&& function, GeneratorWrapper&& generator) { return GeneratorWrapper( - pf::make_unique>(std::forward(function), std::move(generator)) + pf::make_unique>(std::forward(function), std::move(generator)) ); } diff --git a/projects/SelfTest/Baselines/compact.sw.approved.txt b/projects/SelfTest/Baselines/compact.sw.approved.txt index 2fcdd866..5b338078 100644 --- a/projects/SelfTest/Baselines/compact.sw.approved.txt +++ b/projects/SelfTest/Baselines/compact.sw.approved.txt @@ -416,6 +416,9 @@ Generators.tests.cpp:: passed: i % 2 == 0 for: 0 == 0 Generators.tests.cpp:: passed: i.size() == 1 for: 1 == 1 Generators.tests.cpp:: passed: i.size() == 1 for: 1 == 1 Generators.tests.cpp:: passed: i.size() == 1 for: 1 == 1 +Generators.tests.cpp:: passed: i.size() == 1 for: 1 == 1 +Generators.tests.cpp:: passed: i.size() == 1 for: 1 == 1 +Generators.tests.cpp:: passed: i.size() == 1 for: 1 == 1 Generators.tests.cpp:: passed: j > 0 for: 1 > 0 Generators.tests.cpp:: passed: j > 0 for: 2 > 0 Generators.tests.cpp:: passed: j > 0 for: 3 > 0 @@ -495,6 +498,12 @@ GeneratorsImpl.tests.cpp:: passed: gen.get() == 4.0 for: 4.0 == 4.0 GeneratorsImpl.tests.cpp:: passed: gen.next() for: true GeneratorsImpl.tests.cpp:: passed: gen.get() == 6.0 for: 6.0 == 6.0 GeneratorsImpl.tests.cpp:: passed: !(gen.next()) for: !false +GeneratorsImpl.tests.cpp:: passed: gen.get() == 2.0 for: 2.0 == 2.0 +GeneratorsImpl.tests.cpp:: passed: gen.next() for: true +GeneratorsImpl.tests.cpp:: passed: gen.get() == 4.0 for: 4.0 == 4.0 +GeneratorsImpl.tests.cpp:: passed: gen.next() for: true +GeneratorsImpl.tests.cpp:: passed: gen.get() == 6.0 for: 6.0 == 6.0 +GeneratorsImpl.tests.cpp:: passed: !(gen.next()) for: !false GeneratorsImpl.tests.cpp:: passed: gen.get() == 3 for: 3 == 3 GeneratorsImpl.tests.cpp:: passed: !(gen.next()) for: !false GeneratorsImpl.tests.cpp:: passed: gen.get() == 1 for: 1 == 1 diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 3c504378..7fc5583b 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1265,5 +1265,5 @@ due to unexpected exception with message: =============================================================================== test cases: 255 | 189 passed | 62 failed | 4 failed as expected -assertions: 1393 | 1250 passed | 122 failed | 21 failed as expected +assertions: 1402 | 1259 passed | 122 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 5b54ace9..0f7b5404 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -3040,6 +3040,45 @@ Generators -- adapters Generators.tests.cpp: ............................................................................... +Generators.tests.cpp:: PASSED: + REQUIRE( i.size() == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +Generators -- adapters + Transforming elements + Different deduced type +------------------------------------------------------------------------------- +Generators.tests.cpp: +............................................................................... + +Generators.tests.cpp:: PASSED: + REQUIRE( i.size() == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +Generators -- adapters + Transforming elements + Different deduced type +------------------------------------------------------------------------------- +Generators.tests.cpp: +............................................................................... + +Generators.tests.cpp:: PASSED: + REQUIRE( i.size() == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +Generators -- adapters + Transforming elements + Different deduced type +------------------------------------------------------------------------------- +Generators.tests.cpp: +............................................................................... + Generators.tests.cpp:: PASSED: REQUIRE( i.size() == 1 ) with expansion: @@ -3675,7 +3714,44 @@ with expansion: ------------------------------------------------------------------------------- Generators internals - Map + Map with explicit return type +------------------------------------------------------------------------------- +GeneratorsImpl.tests.cpp: +............................................................................... + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( gen.get() == 2.0 ) +with expansion: + 2.0 == 2.0 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( gen.next() ) +with expansion: + true + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( gen.get() == 4.0 ) +with expansion: + 4.0 == 4.0 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( gen.next() ) +with expansion: + true + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE( gen.get() == 6.0 ) +with expansion: + 6.0 == 6.0 + +GeneratorsImpl.tests.cpp:: PASSED: + REQUIRE_FALSE( gen.next() ) +with expansion: + !false + +------------------------------------------------------------------------------- +Generators internals + Map with deduced return type ------------------------------------------------------------------------------- GeneratorsImpl.tests.cpp: ............................................................................... @@ -10850,5 +10926,5 @@ Misc.tests.cpp:: PASSED: =============================================================================== test cases: 255 | 174 passed | 77 failed | 4 failed as expected -assertions: 1409 | 1250 passed | 138 failed | 21 failed as expected +assertions: 1418 | 1259 passed | 138 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 25c48235..f9f8754b 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -4,7 +4,7 @@ loose text artifact - + @@ -360,6 +360,7 @@ Message.tests.cpp: + @@ -373,7 +374,8 @@ Message.tests.cpp: - + + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 637689a4..ec19c14d 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -3736,6 +3736,48 @@ Nor would this +
+
+ + + i.size() == 1 + + + 1 == 1 + + + +
+ +
+
+
+ + + i.size() == 1 + + + 1 == 1 + + + +
+ +
+
+
+ + + i.size() == 1 + + + 1 == 1 + + + +
+ +
@@ -4461,7 +4503,58 @@ Nor would this
-
+
+ + + gen.get() == 2.0 + + + 2.0 == 2.0 + + + + + gen.next() + + + true + + + + + gen.get() == 4.0 + + + 4.0 == 4.0 + + + + + gen.next() + + + true + + + + + gen.get() == 6.0 + + + 6.0 == 6.0 + + + + + !(gen.next()) + + + !false + + + +
+
gen.get() == 2.0 @@ -13153,7 +13246,7 @@ loose text artifact
- + - + diff --git a/projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp b/projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp index de8b0ffc..a57dfc77 100644 --- a/projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp +++ b/projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp @@ -68,7 +68,7 @@ TEST_CASE("Generators internals", "[generators][internals]") { REQUIRE_FALSE(gen.next()); } } - SECTION("Map") { + SECTION("Map with explicit return type") { auto gen = map([] (int i) {return 2.0 * i; }, values({ 1, 2, 3 })); REQUIRE(gen.get() == 2.0); REQUIRE(gen.next()); @@ -77,6 +77,15 @@ TEST_CASE("Generators internals", "[generators][internals]") { REQUIRE(gen.get() == 6.0); REQUIRE_FALSE(gen.next()); } + SECTION("Map with deduced return type") { + auto gen = map([] (int i) {return 2.0 * i; }, values({ 1, 2, 3 })); + REQUIRE(gen.get() == 2.0); + REQUIRE(gen.next()); + REQUIRE(gen.get() == 4.0); + REQUIRE(gen.next()); + REQUIRE(gen.get() == 6.0); + REQUIRE_FALSE(gen.next()); + } SECTION("Repeat") { SECTION("Singular repeat") { auto gen = repeat(1, value(3)); diff --git a/projects/SelfTest/UsageTests/Generators.tests.cpp b/projects/SelfTest/UsageTests/Generators.tests.cpp index 0cf1ce6e..18af838d 100644 --- a/projects/SelfTest/UsageTests/Generators.tests.cpp +++ b/projects/SelfTest/UsageTests/Generators.tests.cpp @@ -144,6 +144,11 @@ TEST_CASE("Generators -- adapters", "[generators][generic]") { auto i = GENERATE(map([] (int val) { return std::to_string(val); }, values({ 1, 2, 3 }))); REQUIRE(i.size() == 1); } + SECTION("Different deduced type") { + // This takes a generator that returns ints and maps them into strings + auto i = GENERATE(map([] (int val) { return std::to_string(val); }, values({ 1, 2, 3 }))); + REQUIRE(i.size() == 1); + } } SECTION("Repeating a generator") { // This will return values [1, 2, 3, 1, 2, 3]