halcheck 1.0
Loading...
Searching...
No Matches
variant.hpp
1#ifndef HALCHECK_GEN_VARIANT_HPP
2#define HALCHECK_GEN_VARIANT_HPP
3
4#include <halcheck/gen/element.hpp>
5#include <halcheck/gen/label.hpp>
6#include <halcheck/lib/atom.hpp>
7#include <halcheck/lib/functional.hpp>
8#include <halcheck/lib/type_traits.hpp>
9#include <halcheck/lib/utility.hpp>
10#include <halcheck/lib/variant.hpp>
11
12#include <cstddef>
13#include <tuple>
14#include <type_traits>
15
16namespace halcheck { namespace gen {
17
18namespace detail {
19template<typename... Fs>
20struct variant_visitor {
21 template<typename T>
22 lib::variant<lib::invoke_result_t<Fs, lib::atom>...> operator()(T i) {
23 using namespace lib::literals;
24 static constexpr auto I = decltype(i)::value;
25 return lib::variant<lib::invoke_result_t<Fs, lib::atom>...>(
26 lib::in_place_index_t<I>(),
27 lib::invoke(std::get<I>(tuple), "gen"_s));
28 }
29 explicit variant_visitor(Fs... gens) : tuple(std::move(gens)...) {}
30 std::tuple<Fs...> tuple;
31};
32} // namespace detail
33
38template<std::size_t... Ints, HALCHECK_REQUIRE(sizeof...(Ints) > 0)>
39lib::variant<std::integral_constant<std::size_t, Ints>...> index(lib::atom id, lib::index_sequence<Ints...> = {}) {
40 using T = lib::variant<std::integral_constant<std::size_t, Ints>...>;
42}
43
50template<typename... Fs, HALCHECK_REQUIRE(lib::conjunction<lib::is_invocable<Fs, lib::atom>...>())>
51lib::variant<lib::invoke_result_t<Fs, lib::atom>...> variant(lib::atom id, Fs... gens) {
52 using namespace lib::literals;
53 auto _ = gen::label(id);
54 auto i = gen::index("index"_s, lib::make_index_sequence<sizeof...(Fs)>{});
55 return lib::visit(detail::variant_visitor<Fs...>(std::move(gens)...), i);
56}
57
58namespace detail {
59template<typename T, typename... Fs>
60struct one_visitor {
61 template<typename I>
62 T operator()(I i) const {
63 using namespace lib::literals;
64 static constexpr auto index = decltype(i)::value;
65 return lib::invoke(std::get<index>(tuple), "gen"_s);
66 }
67 explicit one_visitor(Fs... gens) : tuple(std::move(gens)...) {}
68 std::tuple<Fs...> tuple;
69};
70} // namespace detail
71
79template<typename T, typename... Fs, HALCHECK_REQUIRE(lib::conjunction<lib::is_invocable_r<T, Fs, lib::atom>...>())>
80T one(lib::atom id, lib::in_place_type_t<T>, Fs... gens) {
81 using namespace lib::literals;
82 auto _ = gen::label(id);
83 auto i = gen::index("index"_s, lib::make_index_sequence<sizeof...(Fs)>{});
84 return lib::visit(detail::one_visitor<T, Fs...>(std::move(gens)...), i);
85}
86
95 return gen::one(
96 id,
98 std::move(args)...);
99}
100
101}} // namespace halcheck::gen
102
103#endif
HALCHECK_INLINE_CONSTEXPR struct halcheck::gen::@7 element
Generates a random value from a fixed list of elements.
static struct halcheck::gen::@9 label
Extends the unique identifiers passed to other random generation functions.
lib::variant< lib::symbol, lib::number > atom
An atom is either a symbol or a number.
Definition atom.hpp:194
HALCHECK_INLINE_CONSTEXPR struct halcheck::lib::@20 invoke
An implementation of std::invoke.
decltype(lib::invoke(std::declval< F >(), std::declval< Args >()...)) invoke_result_t
An implementation of std::invoke_result_t.
Definition invoke.hpp:42
typename std::common_type< Args... >::type common_type_t
An implementation of std::common_type_t.
Definition type_traits.hpp:133
#define HALCHECK_REQUIRE(...)
Expands to a template argument that is only valid if the given argument evaluates to true.
Definition type_traits.hpp:24
lib::variant< std::integral_constant< std::size_t, Ints >... > index(lib::atom id, lib::index_sequence< Ints... >={})
Generates a random std::integral_constant from the given set of indices.
Definition variant.hpp:39
T one(lib::atom id, lib::in_place_type_t< T >, Fs... gens)
Generates a value according to a randomly selected generator.
Definition variant.hpp:80
STL namespace.
An implementation of std::conjunction.
Definition type_traits.hpp:59
An implementation of std::integer_sequence.
Definition utility.hpp:53
An implementation of std::is_invocable.
Definition invoke.hpp:66
An implementation of std::make_integer_sequence.
Definition utility.hpp:82