diff --git a/include/autocheck/apply.hpp b/include/autocheck/apply.hpp index 04aedf6..b6fe75a 100644 --- a/include/autocheck/apply.hpp +++ b/include/autocheck/apply.hpp @@ -25,6 +25,7 @@ namespace autocheck { typedef typename std::result_of::type type; }; +#if !defined(__cpp_lib_apply) template typename result_of_apply::type>::type subapply(F f, Tuple&& args, const detail::range<0, Is...>&) { @@ -38,6 +39,7 @@ namespace autocheck { std::forward(args), detail::range::type>::value>()); } +#endif } diff --git a/include/autocheck/generator.hpp b/include/autocheck/generator.hpp index be4c90f..66a7121 100644 --- a/include/autocheck/generator.hpp +++ b/include/autocheck/generator.hpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -22,11 +25,25 @@ namespace autocheck { return rng; } + template + T construct(const std::tuple& args, + const detail::range<0, Is...>&) + { + return T{ std::get(args)... }; + } + + template + T construct(const std::tuple& args) + { + return autocheck::construct(args, + detail::range()); + } + template T generate(std::tuple& gens, size_t size, const detail::range<0, Is...>&) { - return T(std::get(gens)(size)...); + return T{ std::get(gens)(size)... }; } template @@ -82,7 +99,7 @@ namespace autocheck { size = std::numeric_limits::max(); } /* Distribution is non-static. */ - std::uniform_int_distribution dist(0, size); + std::uniform_int_distribution dist(0, static_cast(size)); auto i = dist(rng()); auto rv = (size < detail::nalnums) ? detail::alnums[i] : @@ -120,7 +137,7 @@ namespace autocheck { result_type operator() (size_t size = 0) { /* Distribution is non-static. */ - std::uniform_int_distribution dist(0, size); + std::uniform_int_distribution dist(0, static_cast(size)); auto rv = dist(rng()); return rv; } @@ -240,40 +257,95 @@ namespace autocheck { class generator> : public string_generator> {}; - /* TODO: Generic sequence generator. */ - - template + template class Container = std::vector, typename... ContainerArgs> class list_generator { private: Gen eltgen; + std::tuple args; public: - list_generator(const Gen& eltgen = Gen()) : - eltgen(eltgen) {} + template > + list_generator(const Gen& eltgen = Gen(), const Tuple& args = Tuple()) : + eltgen(eltgen), args(args) {} - typedef std::vector result_type; + typedef Container result_type; result_type operator() (size_t size = 0) { - result_type rv; - rv.reserve(size); - std::generate_n(std::back_insert_iterator(rv), size, + auto rv = autocheck::construct(args); + std::generate_n(std::insert_iterator(rv, rv.end()), size, fix(size, eltgen)); return rv; } }; + namespace detail { + template class Container, typename T, typename... Others> + struct map_for; + + template class Container, typename F, typename S, typename... Others> + struct map_for, Others...> + { + using type = Container; + }; + + template + using map_for_t = typename map_for::type; + + template + using unordered_map_for_t = typename map_for::type; + } + template - list_generator list_of(const Gen& gen) { - return list_generator(gen); + list_generator list_of(const Gen& gen) { + return list_generator(gen); } template > - list_generator list_of() { + list_generator list_of() { return list_of(Gen()); } - template - class generator> : public list_generator> {}; + template + list_generator set_of(const Gen& gen) { + return list_generator(gen); + } + + template > + list_generator set_of() { + return set_of(Gen()); + } + + template + list_generator map_of(const Gen& gen) { + return list_generator(gen); + } + + template > + list_generator map_of() { + return map_of(Gen()); + } + + template + list_generator unordered_map_of(const Gen& gen) { + return list_generator(gen); + } + + template > + list_generator unordered_map_of() { + return unordered_map_of(Gen()); + } + + template + class generator> : public list_generator, std::vector, A> {}; + + template + class generator> : public list_generator, std::set, C, A> {}; + + template + class generator> : public list_generator>, detail::map_for_t, C, A> {}; + + template + class generator> : public list_generator>, detail::unordered_map_for_t, C, A> {}; /* Ordered list combinator. */ @@ -334,6 +406,36 @@ namespace autocheck { cons_generator...> cons() { return cons_generator...>(); } + + template + class generator> : public cons_generator, generator...> {}; + + template + cons_generator, Gens...> tuple(const Gens&... gens) { + return cons_generator, Gens...>(gens...); + } + + template + class constant_generator + { + public: + constant_generator(T value) : value(value) {} + + using result_type = T; + + result_type operator() (size_t = 0) + { + return value; + } + private: + T value; + }; + + template + constant_generator constant(T value) + { + return constant_generator(value); + } } #endif diff --git a/include/autocheck/ostream.hpp b/include/autocheck/ostream.hpp index 4187061..4f870c8 100644 --- a/include/autocheck/ostream.hpp +++ b/include/autocheck/ostream.hpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include /* Forward declarations of output stream operators. */ @@ -15,6 +18,15 @@ namespace autocheck { template std::ostream& operator<< (std::ostream& out, const std::vector& seq); + template + std::ostream& operator<< (std::ostream& out, const std::set& seq); + + template + std::ostream& operator<< (std::ostream& out, const std::map& seq); + + template + std::ostream& operator<< (std::ostream& out, const std::unordered_map& seq); + } #endif diff --git a/include/autocheck/sequence.hpp b/include/autocheck/sequence.hpp index 5efcb59..308db04 100644 --- a/include/autocheck/sequence.hpp +++ b/include/autocheck/sequence.hpp @@ -21,6 +21,54 @@ namespace autocheck { return out; } + template + std::ostream& operator<< (std::ostream& out, const std::set& seq) { + out << "["; + bool first = true; + for (auto b = seq.begin(), e = seq.end(); b != e; ++b) { + if (first) { + first = false; + } else { + out << ", "; + } + out << *b; + } + out << "]"; + return out; + } + + template + std::ostream& operator<< (std::ostream& out, const std::map& seq) { + out << "["; + bool first = true; + for (auto b = seq.begin(), e = seq.end(); b != e; ++b) { + if (first) { + first = false; + } else { + out << ", "; + } + out << *b; + } + out << "]"; + return out; + } + + template + std::ostream& operator<< (std::ostream& out, const std::unordered_map& seq) { + out << "["; + bool first = true; + for (auto b = seq.begin(), e = seq.end(); b != e; ++b) { + if (first) { + first = false; + } else { + out << ", "; + } + out << *b; + } + out << "]"; + return out; + } + } #endif