halcheck 1.0
Loading...
Searching...
No Matches
arbitrary.hpp
1#ifndef HALCHECK_GEN_ARBITRARY_HPP
2#define HALCHECK_GEN_ARBITRARY_HPP
3
10#include <halcheck/gen/container.hpp>
11#include <halcheck/gen/label.hpp>
12#include <halcheck/gen/optional.hpp>
13#include <halcheck/gen/sample.hpp>
14#include <halcheck/gen/shrink.hpp>
15#include <halcheck/gen/variant.hpp>
16#include <halcheck/lib/atom.hpp>
17#include <halcheck/lib/iterator.hpp>
18#include <halcheck/lib/optional.hpp>
19#include <halcheck/lib/scope.hpp>
20#include <halcheck/lib/type_traits.hpp>
21#include <halcheck/lib/variant.hpp>
22
23#include <climits>
24#include <cstdint>
25#include <cstring>
26#include <limits>
27#include <tuple>
28#include <utility>
29
30namespace halcheck { namespace gen {
31
32namespace detail {
38template<typename T>
39struct tag {};
40} // namespace detail
41
42using detail::tag;
43
44namespace detail {
45template<typename T>
46using is_arbitrary_helper = lib::enable_if_t<
48} // namespace detail
49
67template<typename T>
68struct is_arbitrary : lib::is_detected<detail::is_arbitrary_helper, lib::remove_cv_t<T>> {};
69
78template<typename T, HALCHECK_REQUIRE(is_arbitrary<T>())>
80 return arbitrary(gen::tag<lib::decay_t<T>>(), id);
81}
82
83namespace detail {
84inline lib::monostate arbitrary(gen::tag<lib::monostate>, lib::atom) { return {}; }
85
86inline bool arbitrary(gen::tag<bool>, lib::atom id) { return gen::sample(id, 1) > 0 && !gen::shrink(id); }
87
88template<typename T, HALCHECK_REQUIRE(std::is_integral<T>())>
89T arbitrary(gen::tag<T>, lib::atom id) {
90 auto src = gen::sample(id);
91 T dst;
92 std::memcpy(&dst, &src, sizeof(dst));
93 return gen::shrink_to(id, T(0), dst);
94}
95
96template<typename T, HALCHECK_REQUIRE(std::is_floating_point<T>())>
97T arbitrary(gen::tag<T>, lib::atom id) {
100}
101
102template<typename T, typename U, HALCHECK_REQUIRE(gen::is_arbitrary<T>()), HALCHECK_REQUIRE(gen::is_arbitrary<U>())>
104 auto _ = gen::label(id);
106}
107
108template<typename... Ts, HALCHECK_REQUIRE(lib::conjunction<gen::is_arbitrary<Ts>...>())>
109std::tuple<Ts...> arbitrary(gen::tag<std::tuple<Ts...>>, lib::atom id) {
110 auto _ = gen::label(id);
111 std::uintmax_t i = 0;
112 return std::tuple<Ts...>{gen::arbitrary<Ts>(i++)...};
113}
114
115template<typename T, HALCHECK_REQUIRE(gen::is_arbitrary<T>())>
116lib::optional<T> arbitrary(gen::tag<lib::optional<T>>, lib::atom id) {
118}
119
120template<typename... Ts, HALCHECK_REQUIRE(lib::conjunction<gen::is_arbitrary<Ts>...>())>
121lib::variant<Ts...> arbitrary(gen::tag<lib::variant<Ts...>>, lib::atom id) {
122 return gen::variant(id, gen::arbitrary<Ts>...);
123}
124
125template<
126 typename Container,
127 HALCHECK_REQUIRE(lib::is_insertable_range<Container>()),
129Container arbitrary(gen::tag<Container>, lib::atom id) {
131}
132} // namespace detail
133
134}} // namespace halcheck::gen
135
136#endif
T arbitrary(lib::atom id)
Generates an arbitrary value of a given type.
Definition arbitrary.hpp:79
static struct halcheck::gen::@9 label
Extends the unique identifiers passed to other random generation functions.
HALCHECK_INLINE_CONSTEXPR struct halcheck::gen::@11 sample
Obtains a random value.
lib::variant< lib::symbol, lib::number > atom
An atom is either a symbol or a number.
Definition atom.hpp:194
lib::iter_value_t< lib::iterator_t< R > > range_value_t
The type of element contained in a range.
Definition range.hpp:332
typename std::decay< T >::type decay_t
An implementation of std::decay_t.
Definition type_traits.hpp:101
typename std::enable_if< Cond, T >::type enable_if_t
An implementation of std::enable_if_t.
Definition type_traits.hpp:93
#define HALCHECK_REQUIRE(...)
Expands to a template argument that is only valid if the given argument evaluates to true.
Definition type_traits.hpp:24
T make_pair(T... args)
T max(T... args)
T memcpy(T... args)
T container(lib::atom id, F gen)
Generates a random container value.
Definition container.hpp:127
HALCHECK_INLINE_CONSTEXPR struct halcheck::gen::@10 optional
Generates a lib::optional.
lib::variant< lib::invoke_result_t< Fs, lib::atom >... > variant(lib::atom id, Fs... gens)
Constructs a random variant.
Definition variant.hpp:51
Determines if a type supports generating arbitrary values.
Definition arbitrary.hpp:68
An implementation of std::experimental::is_detected.
Definition type_traits.hpp:247