cauldron  0.0.0
 All Classes Namespaces Files Functions Variables Typedefs
sieve.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <functional>
4 #include <string>
5 #include <vector>
6 
7 
8 namespace cauldron {
9 static const unsigned MAX_CYCLES = 1'000;
10 
11 template<typename Product>
12 using Requirement = std::function<bool(Product)>;
13 
14 
15 class OutOfCycles : public std::exception {
16  public:
17  explicit OutOfCycles(unsigned max_cycles) :
18  msg_("Could not find any satisfactory product in "
19  + std::to_string(max_cycles)
20  + " cycles") {};
21 
22  const char *what() const throw() override {
23  return msg_.c_str();
24  }
25 
26  private:
27  std::string msg_;
28 };
29 
30 
31 template<typename Product>
32 class Sieve {
33  public:
34  explicit Sieve(unsigned max_cycles = MAX_CYCLES) :
35  max_cycles_(max_cycles) {};
36 
37  Sieve(std::initializer_list<Requirement<Product>> requirements,
38  unsigned max_cycles = MAX_CYCLES) :
39  requirements_(requirements),
40  max_cycles_(max_cycles) {}
41 
42  explicit Sieve(const std::vector<Requirement<Product>> &requirements,
43  unsigned max_cycles = MAX_CYCLES) :
44  requirements_(requirements),
45  max_cycles_(max_cycles) {}
46 
47  bool satisfactory(Product product) const {
48  for (const auto &requirement: requirements_) {
49  bool satisfies_requirement = requirement(product);
50  if (!satisfies_requirement) {
51  return false;
52  }
53  }
54  return true;
55  }
56 
57  Sieve<Product> expand(const Requirement<Product> &requirement) const {
58  std::vector<Requirement<Product>> requirements(requirements_);
59  requirements.push_back(requirement);
60  return Sieve<Product>(requirements,
61  max_cycles_);
62  }
63 
64  Product sift(std::function<Product()> producer) const {
65  for (unsigned _ = 0; _ < max_cycles_; ++_) {
66  Product product = producer();
67  if (!satisfactory(product)) {
68  continue;
69  }
70  return product;
71  }
72  throw OutOfCycles(max_cycles_);
73  }
74 
75  protected:
76  std::vector<Requirement<Product>> requirements_;
77  unsigned max_cycles_;
78 };
79 }