From b6c75110e63902ff4a92cb4c4ac1f83527210904 Mon Sep 17 00:00:00 2001 From: Oleh Stolyar Date: Fri, 14 Dec 2018 12:35:40 +0000 Subject: [PATCH] Prefer T(...) over T{...} when they behave differently ...in gen::construct and gen::makeUnique. Also, add support for aggregate initialization in gen::makeShared and tests for all of them. --- include/rapidcheck/detail/ApplyTuple.h | 6 +-- include/rapidcheck/gen/Build.hpp | 58 +++++++++++++++++++++----- test/gen/BuildTests.cpp | 43 +++++++++++++++++++ test/util/Aggregate.h | 23 ++++++++++ 4 files changed, 116 insertions(+), 14 deletions(-) create mode 100644 test/util/Aggregate.h diff --git a/include/rapidcheck/detail/ApplyTuple.h b/include/rapidcheck/detail/ApplyTuple.h index a664c18f..079e7721 100644 --- a/include/rapidcheck/detail/ApplyTuple.h +++ b/include/rapidcheck/detail/ApplyTuple.h @@ -13,7 +13,7 @@ struct ApplyTupleImpl; template struct ApplyTupleImpl, Callable, IndexSequence> { - using ReturnType = typename std::result_of::type; + using ReturnType = typename std::result_of::type; static ReturnType apply(std::tuple &&tuple, Callable &&callable) { return callable(std::move(std::get(tuple))...); @@ -24,7 +24,7 @@ template struct ApplyTupleImpl &, Callable, IndexSequence> { - using ReturnType = typename std::result_of::type; + using ReturnType = typename std::result_of::type; static ReturnType apply(std::tuple &tuple, Callable &&callable) { return callable(std::get(tuple)...); @@ -35,7 +35,7 @@ template struct ApplyTupleImpl &, Callable, IndexSequence> { - using ReturnType = typename std::result_of::type; + using ReturnType = typename std::result_of::type; static ReturnType apply(const std::tuple &tuple, Callable &&callable) { return callable(std::get(tuple)...); diff --git a/include/rapidcheck/gen/Build.hpp b/include/rapidcheck/gen/Build.hpp index 9436fd78..8b7b9f3d 100644 --- a/include/rapidcheck/gen/Build.hpp +++ b/include/rapidcheck/gen/Build.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "rapidcheck/gen/Tuple.h" #include "rapidcheck/detail/ApplyTuple.h" @@ -119,6 +121,41 @@ class BuildMapper, Lenses...> { std::tuple m_lenses; }; +template +typename std::enable_if::value, T>::type +construct(Args &&... args) { + return T(std::forward(args)...); +} + +template +typename std::enable_if::value, T>::type +construct(Args &&... args) { + return T{std::forward(args)...}; +} + +template +typename std::enable_if::value, std::unique_ptr>::type +makeUnique(Args &&... args) { + return std::unique_ptr(new T(std::forward(args)...)); +} + +template +typename std::enable_if::value, std::unique_ptr>::type +makeUnique(Args &&... args) { + return std::unique_ptr(new T{std::forward(args)...}); +} + +template +typename std::enable_if::value, std::shared_ptr>::type +makeShared(Args &&... args) { + return std::make_shared(std::forward(args)...); +} + +template +typename std::enable_if::value, std::shared_ptr>::type +makeShared(Args &&... args) { + return std::shared_ptr(new T{std::forward(args)...}); +} } // namespace detail template @@ -126,8 +163,9 @@ Gen construct(Gen... gens) { return gen::map(gen::tuple(std::move(gens)...), [](std::tuple &&argsTuple) { return rc::detail::applyTuple( - std::move(argsTuple), - [](Args &&... args) { return T{std::move(args)...}; }); + std::forward>(argsTuple), + detail::construct + ); }); } @@ -141,10 +179,9 @@ Gen> makeUnique(Gen... gens) { return gen::map(gen::tuple(std::move(gens)...), [](std::tuple &&argsTuple) { return rc::detail::applyTuple( - std::move(argsTuple), - [](Args &&... args) { - return std::unique_ptr(new T{std::move(args)...}); - }); + std::forward>(argsTuple), + detail::makeUnique + ); }); } @@ -152,11 +189,10 @@ template Gen> makeShared(Gen... gens) { return gen::map(gen::tuple(std::move(gens)...), [](std::tuple &&argsTuple) { - return rc::detail::applyTuple(std::move(argsTuple), - [](Args &&... args) { - return std::make_shared( - std::move(args)...); - }); + return rc::detail::applyTuple( + std::forward>(argsTuple), + detail::makeShared + ); }); } diff --git a/test/gen/BuildTests.cpp b/test/gen/BuildTests.cpp index e2e8a3c5..6629ba96 100644 --- a/test/gen/BuildTests.cpp +++ b/test/gen/BuildTests.cpp @@ -1,6 +1,7 @@ #include #include +#include "util/Aggregate.h" #include "util/GenUtils.h" #include "util/Predictable.h" #include "util/Logger.h" @@ -90,6 +91,20 @@ TEST_CASE("gen::construct") { RC_ASSERT(isArbitraryPredictable(std::get<0>(value))); RC_ASSERT(isArbitraryPredictable(std::get<1>(value))); } + + SECTION("works with aggregate initializers") { + gen::construct(gen::arbitrary(), + gen::arbitrary()); + gen::construct(gen::arbitrary(), + gen::arbitrary(), + gen::arbitrary()); + } + + SECTION("prefers T(x, y) over T{x, y} when they behave differently") { + auto a = gen::construct>(gen::just(3), gen::just(3))(Random(), 0).value(); + std::vector b(3, 3); + RC_ASSERT(a == b); + } } TEST_CASE("gen::makeUnique") { @@ -122,6 +137,20 @@ TEST_CASE("gen::makeUnique") { RC_ASSERT(isArbitraryPredictable(std::get<0>(value))); RC_ASSERT(isArbitraryPredictable(std::get<1>(value))); } + + SECTION("works with aggregate initializers") { + gen::makeUnique(gen::arbitrary(), + gen::arbitrary()); + gen::makeUnique(gen::arbitrary(), + gen::arbitrary(), + gen::arbitrary()); + } + + SECTION("prefers T(x, y) over T{x, y} when they behave differently") { + auto a = gen::makeUnique>(gen::just(3), gen::just(3))(Random(), 0).value(); + auto b = std::unique_ptr>(new std::vector(3, 3)); + RC_ASSERT(*a == *b); + } } TEST_CASE("gen::makeShared") { @@ -154,6 +183,20 @@ TEST_CASE("gen::makeShared") { RC_ASSERT(isArbitraryPredictable(std::get<0>(value))); RC_ASSERT(isArbitraryPredictable(std::get<1>(value))); } + + SECTION("works with aggregate initializers") { + gen::makeShared(gen::arbitrary(), + gen::arbitrary()); + gen::makeShared(gen::arbitrary(), + gen::arbitrary(), + gen::arbitrary()); + } + + SECTION("prefers T(x, y) over T{x, y} when they behave differently") { + auto a = gen::makeShared>(gen::just(3), gen::just(3))(Random(), 0).value(); + auto b = std::shared_ptr>(new std::vector(3, 3)); + RC_ASSERT(*a == *b); + } } namespace { diff --git a/test/util/Aggregate.h b/test/util/Aggregate.h new file mode 100644 index 00000000..75e8cf6c --- /dev/null +++ b/test/util/Aggregate.h @@ -0,0 +1,23 @@ +#pragma once + +#include "rapidcheck.h" + +namespace rc { + struct Aggregate { + int x; + int y; + }; + + template<> + struct Arbitrary { + static Gen arbitrary() { + return gen::construct(gen::arbitrary(), + gen::arbitrary()); + } + }; + + struct NestedAggregate { + Aggregate a; + int z; + }; +} // namespace rc