Skip to content

Commit

Permalink
Give a more helpful error message when Gen is constructed with incomp…
Browse files Browse the repository at this point in the history
…atible type

This produces a compile error in Gen's constructor.  Before this change,
errors would be attributed to GenImpl.
  • Loading branch information
cirodrig committed Sep 16, 2017
1 parent 1316b6d commit c909988
Showing 1 changed file with 19 additions and 1 deletion.
20 changes: 19 additions & 1 deletion include/rapidcheck/Gen.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <type_traits>
#include <cassert>

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

} // namespace gen

// Concept check for types that have method
// `Shrinkable<T> G::operator()(const Random &, int) const`
template<typename T, typename G, typename = void>
struct MakesShrinkable : std::false_type {};

template<typename T, typename G>
struct MakesShrinkable<T, G, typename std::enable_if<
std::is_convertible<
decltype(std::declval<const G>()(std::declval<Random>(), 0)),
Shrinkable<T> >::value>::type>
: std::true_type {};

template <typename T>
class Gen<T>::IGenImpl {
public:
Expand Down Expand Up @@ -55,7 +68,12 @@ class Gen<T>::GenImpl : public IGenImpl {
template <typename T>
template <typename Impl, typename>
Gen<T>::Gen(Impl &&impl)
: m_impl(new GenImpl<Decay<Impl>>(std::forward<Impl>(impl))) {}
: m_impl(new GenImpl<Decay<Impl>>(std::forward<Impl>(impl))) {
static_assert(MakesShrinkable<T, Impl>::value,
"Generator implementation must have a method Shrinkable<T> operator()(const Random &, int) const");
static_assert(std::is_copy_constructible<Impl>::value,
"Generator implementation must have a copy constructor");
}

template <typename T>
std::string Gen<T>::name() const {
Expand Down

0 comments on commit c909988

Please sign in to comment.