ZeroErr
container_of.h
Go to the documentation of this file.
1 #pragma once
3 
6 
8 
9 namespace zeroerr {
10 
12  int min_size = 0, max_size = 100, size = -1;
13 
14  void WithMaxSize(unsigned _max_size) { this->max_size = _max_size; }
15  void WithMinSize(unsigned _min_size) { this->min_size = _min_size; }
16  void WithSize(unsigned _size) { this->size = _size; }
17 };
18 
19 
20 template <typename T, typename InnerDomain>
21 class AssociativeContainerOf : public Domain<T, std::vector<typename InnerDomain::CorpusType>>,
22  public ContainerOfBase {
23  InnerDomain inner_domain;
24 
25 public:
26  using ValueType = T;
27  using CorpusType = std::vector<typename InnerDomain::CorpusType>;
28 
29  AssociativeContainerOf(InnerDomain&& inner_domain) : inner_domain(std::move(inner_domain)) {}
30 
31  virtual ValueType GetValue(const CorpusType& v) const override {
32  ValueType result;
33  for (const auto& elem : v) {
34  result.insert(inner_domain.GetValue(elem));
35  }
36  return result;
37  }
38 
39  virtual CorpusType FromValue(const ValueType& v) const override {
40  CorpusType result;
41  for (const auto& elem : v) {
42  result.push_back(inner_domain.FromValue(elem));
43  }
44  return result;
45  }
46 
47  CorpusType GetRandomCorpus(Rng& rng) const override {
48  unsigned E = rng.bounded(max_size - min_size + 1) + min_size;
49  CorpusType result;
50  for (unsigned i = 0; i < E; i++) {
51  result.push_back(inner_domain.GetRandomCorpus(rng));
52  }
53  return result;
54  }
55 
56  void Mutate(Rng& rng, CorpusType& v, bool only_shrink) const override {
57  int action = rng.bounded(5);
58  if (size == -1 && action == 0) {
59  if (static_cast<int>(v.size()) > min_size)
60  v.erase(v.begin() + rng.bounded(static_cast<uint32_t>(v.size())));
61 
62  } else if (size == -1 && action == 1) {
63  if (static_cast<int>(v.size()) < max_size)
64  v.push_back(inner_domain.GetRandomCorpus(rng));
65 
66  } else {
67  inner_domain.Mutate(rng, v[rng.bounded(static_cast<uint32_t>(v.size()))], only_shrink);
68  }
69  }
70 };
71 
72 template <typename T, typename InnerDomain>
73 class SequenceContainerOf : public Domain<T, std::vector<typename InnerDomain::CorpusType>>,
74  public ContainerOfBase {
75  InnerDomain inner_domain;
76 
77 public:
78  using ValueType = T;
79  using CorpusType = std::vector<typename InnerDomain::CorpusType>;
80 
81  SequenceContainerOf(InnerDomain&& inner_domain) : inner_domain(std::move(inner_domain)) {}
82 
83  virtual ValueType GetValue(const CorpusType& v) const override {
84  return ValueType(v.begin(), v.end());
85  }
86  virtual CorpusType FromValue(const ValueType& v) const override {
87  return CorpusType(v.begin(), v.end());
88  }
89 
90  CorpusType GetRandomCorpus(Rng& rng) const override {
91  unsigned E = rng.bounded(max_size - min_size + 1) + min_size;
92  CorpusType result;
93  for (unsigned i = 0; i < E; i++) {
94  result.push_back(inner_domain.GetRandomCorpus(rng));
95  }
96  return result;
97  }
98 
99  void Mutate(Rng& rng, CorpusType& v, bool only_shrink) const override {
100  int action = rng.bounded(5);
101  if (size == -1 && action == 0) {
102  if (static_cast<int>(v.size()) > min_size) v.erase(v.begin() + rng.bounded(static_cast<uint32_t>(v.size())));
103 
104  } else if (size == -1 && action == 1) {
105  if (static_cast<int>(v.size()) < max_size)
106  v.push_back(inner_domain.GetRandomCorpus(rng));
107  } else {
108  inner_domain.Mutate(rng, v[rng.bounded(static_cast<uint32_t>(v.size()))], only_shrink);
109  }
110  }
111 };
112 
113 
114 // ContainerOf<T>(inner) combinator creates a domain for a container T (eg, a
115 // std::vector, std::set, etc) where elements are created from `inner`.
116 //
117 // Example usage:
118 //
119 // ContainerOf<std::vector<int>>(InRange(1, 2021))
120 //
121 // The domain also supports customizing the minimum and maximum size via the
122 // `WithSize`, `WithMinSize` and `WithMaxSize` functions. Eg:
123 //
124 // ContainerOf<std::vector<int>>(Arbitrary<int>()).WithMaxSize(5)
125 //
126 template <typename T, typename Inner>
127 typename std::enable_if<detail::is_associative_container<T>::value,
128  AssociativeContainerOf<T, Inner>>::type
129 ContainerOf(Inner&& inner) {
130  return AssociativeContainerOf<T, Inner>(std::move(inner));
131 }
132 
133 template <typename T, typename Inner>
134 typename std::enable_if<!detail::is_associative_container<T>::value &&
135  detail::is_container<T>::value,
136  SequenceContainerOf<T, Inner>>::type
137 ContainerOf(Inner&& inner) {
138  return SequenceContainerOf<T, Inner>(std::move(inner));
139 }
140 
141 // We can also support with a template template parameter, so that we can use
142 // the name of the container instead of the complete type. In such case,
143 // the ValueType of the inner domain should be passed into the container
144 //
145 // ContainerOf<std::vector>(Positive<int>()).WithSize(3);
146 //
147 template <template <typename, typename...> class T, typename... Inner,
148  typename C = T<typename Inner::ValueType...>>
149 auto ContainerOf(Inner... inner) -> decltype(ContainerOf<C>(std::move(inner)...)) {
150  return ContainerOf<C>(std::move(inner)...);
151 }
152 
153 
154 } // namespace zeroerr
155 
Definition: container_of.h:22
std::vector< typename InnerDomain::CorpusType > CorpusType
Definition: container_of.h:27
AssociativeContainerOf(InnerDomain &&inner_domain)
Definition: container_of.h:29
void Mutate(Rng &rng, CorpusType &v, bool only_shrink) const override
Definition: container_of.h:56
T ValueType
Definition: container_of.h:26
CorpusType GetRandomCorpus(Rng &rng) const override
Definition: container_of.h:47
virtual CorpusType FromValue(const ValueType &v) const override
Definition: container_of.h:39
virtual ValueType GetValue(const CorpusType &v) const override
Definition: container_of.h:31
Domain class for generating random values of a specific type.
Definition: domain.h:22
Definition: rng.h:30
uint32_t bounded(uint32_t range) noexcept
Definition: rng.h:126
Definition: container_of.h:74
SequenceContainerOf(InnerDomain &&inner_domain)
Definition: container_of.h:81
virtual ValueType GetValue(const CorpusType &v) const override
Definition: container_of.h:83
void Mutate(Rng &rng, CorpusType &v, bool only_shrink) const override
Definition: container_of.h:99
CorpusType GetRandomCorpus(Rng &rng) const override
Definition: container_of.h:90
virtual CorpusType FromValue(const ValueType &v) const override
Definition: container_of.h:86
T ValueType
Definition: container_of.h:78
std::vector< typename InnerDomain::CorpusType > CorpusType
Definition: container_of.h:79
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition: config.h:265
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition: config.h:218
Definition: benchmark.cpp:17
std::enable_if< detail::is_associative_container< T >::value, AssociativeContainerOf< T, Inner > >::type ContainerOf(Inner &&inner)
Definition: container_of.h:129
Definition: container_of.h:11
int min_size
Definition: container_of.h:12
void WithSize(unsigned _size)
Definition: container_of.h:16
void WithMaxSize(unsigned _max_size)
Definition: container_of.h:14
int max_size
Definition: container_of.h:12
int size
Definition: container_of.h:12
void WithMinSize(unsigned _min_size)
Definition: container_of.h:15