diff --git a/include/autocheck/apply.hpp b/include/autocheck/apply.hpp index 1294e3b..04aedf6 100644 --- a/include/autocheck/apply.hpp +++ b/include/autocheck/apply.hpp @@ -9,11 +9,13 @@ namespace autocheck { /* To extend for more fixed-size containers, just overload result_of_apply, * std::tuple_size, and std::get. */ - template - struct range : range {}; + namespace detail { + template + struct range : range {}; - template - struct range<0, Is...> {}; + template + struct range<0, Is...> {}; + } template struct result_of_apply {}; @@ -23,18 +25,18 @@ namespace autocheck { typedef typename std::result_of::type type; }; + template + typename result_of_apply::type>::type + subapply(F f, Tuple&& args, const detail::range<0, Is...>&) { + return f(std::get(std::forward(args))...); + } + template typename result_of_apply::type>::type apply(F f, Tuple&& args) { return subapply(f, std::forward(args), - range::type>::value>()); - } - - template - typename result_of_apply::type>::type - subapply(F f, Tuple&& args, const range<0, Is...>&) { - return f(std::get(std::forward(args))...); + detail::range::type>::value>()); } } diff --git a/include/autocheck/generator.hpp b/include/autocheck/generator.hpp index f7b5d69..be4c90f 100644 --- a/include/autocheck/generator.hpp +++ b/include/autocheck/generator.hpp @@ -1,6 +1,7 @@ #ifndef AUTOCHECK_GENERATOR_HPP #define AUTOCHECK_GENERATOR_HPP +#include #include #include #include @@ -23,14 +24,15 @@ namespace autocheck { template T generate(std::tuple& gens, size_t size, - const range<0, Is...>&) + const detail::range<0, Is...>&) { return T(std::get(gens)(size)...); } template T generate(std::tuple& gens, size_t size) { - return autocheck::generate(gens, size, range()); + return autocheck::generate(gens, size, + detail::range()); } /* Generators produce an infinite sequence. */ @@ -144,6 +146,42 @@ namespace autocheck { } }; + /** Generate values in the range [low, high). */ + template + class range_generator { + private: + SignedIntegral low; + SignedIntegral len; + generator igen; + + public: + range_generator(const SignedIntegral& low, const SignedIntegral& high) : + low(low), len(high - low) + { + assert(len > 0); + } + + typedef SignedIntegral result_type; + + result_type operator() (size_t size = 0) { + auto i = igen(size) % len; + i = (i > 0) ? i : (i + len); + return low + i; + } + }; + + template + range_generator range( + const SignedIntegral& low, const SignedIntegral& high) + { + return range_generator(low, high); + } + + template + range_generator range(const SignedIntegral& high) { + return range(0, high); + } + template class generator< Floating, @@ -271,7 +309,7 @@ namespace autocheck { std::tuple gens; public: - cons_generator() + cons_generator() #ifndef _MSC_VER : gens(Gens()...) #endif