Skip to content

Commit c909988

Browse files
committed
Give a more helpful error message when Gen is constructed with incompatible type
This produces a compile error in Gen's constructor. Before this change, errors would be attributed to GenImpl.
1 parent 1316b6d commit c909988

1 file changed

Lines changed: 19 additions & 1 deletion

File tree

include/rapidcheck/Gen.hpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include <type_traits>
34
#include <cassert>
45

56
#include "rapidcheck/detail/Any.h"
@@ -17,6 +18,18 @@ Gen<Decay<typename std::result_of<Mapper(T)>::type>> map(Gen<T> gen,
1718

1819
} // namespace gen
1920

21+
// Concept check for types that have method
22+
// `Shrinkable<T> G::operator()(const Random &, int) const`
23+
template<typename T, typename G, typename = void>
24+
struct MakesShrinkable : std::false_type {};
25+
26+
template<typename T, typename G>
27+
struct MakesShrinkable<T, G, typename std::enable_if<
28+
std::is_convertible<
29+
decltype(std::declval<const G>()(std::declval<Random>(), 0)),
30+
Shrinkable<T> >::value>::type>
31+
: std::true_type {};
32+
2033
template <typename T>
2134
class Gen<T>::IGenImpl {
2235
public:
@@ -55,7 +68,12 @@ class Gen<T>::GenImpl : public IGenImpl {
5568
template <typename T>
5669
template <typename Impl, typename>
5770
Gen<T>::Gen(Impl &&impl)
58-
: m_impl(new GenImpl<Decay<Impl>>(std::forward<Impl>(impl))) {}
71+
: m_impl(new GenImpl<Decay<Impl>>(std::forward<Impl>(impl))) {
72+
static_assert(MakesShrinkable<T, Impl>::value,
73+
"Generator implementation must have a method Shrinkable<T> operator()(const Random &, int) const");
74+
static_assert(std::is_copy_constructible<Impl>::value,
75+
"Generator implementation must have a copy constructor");
76+
}
5977

6078
template <typename T>
6179
std::string Gen<T>::name() const {

0 commit comments

Comments
 (0)