Crombie Tools
ObjectStore.h
Go to the documentation of this file.
1 #ifndef CROMBIE_STOREPARTICLES_H
2 #define CROMBIE_STOREPARTICLES_H 1
3 
4 #include <utility>
5 #include <vector>
6 #include <functional>
7 
8 #include <iostream>
9 
10 namespace crombie {
11  namespace ObjectStore {
12 
13  /**
14  @class ObjectStore
15  @brief A generic class for storing a short vector of related particles,
16  including information about the eventual output branche and extra sidecar info.
17 
18  @param E is the enum class used to enumerate branches in the eventual output tree (see crombie maketree) for details.
19  @param T is the type of object pointer to store. This object pointer must also be the input type for the comparison function.
20  @param S is the type of the sidecar information to store. Can be a complicated struct, if you'd like.
21  @param F is the return type of the comparison function.
22  */
23  template<typename E, typename T, typename S = void*, typename F = float>
24  class ObjectStore {
25  public:
26 
27  enum class order {
28  eAsc,
29  eDesc
30  };
31 
32  ObjectStore(const std::vector<E> sorted_enums,
33  const std::function<F(const T&)> compare,
34  const order which = order::eDesc)
35  : compare(compare), which_order(which), total(sorted_enums.size()) {
36  for (auto valid_enum : sorted_enums)
37  store.push_back({valid_enum, nullptr, {}, {}});
38  }
39 
41 
42  struct Particle {
43  const E branch;
44  const T* particle;
45  S extra;
46  F result;
47  };
48 
49  std::vector<Particle> store;
50 
51  void check (const T& obj, S extra = {}) {
52  F result = compare(obj);
53  // Get the first empty iterator or the end
54  auto it = store.begin() + num_filled;
55  if (num_filled < total)
56  num_filled++;
57  // Insertion sort: find location
58  for (;it != store.begin(); --it) {
59  // Keep this stable
60  if ((result == (it - 1)->result) ||
61  ((result < (it - 1)->result) == (which_order == order::eDesc))
62  )
63  break;
64  }
65  // Insertion sort: move elements down
66  for(auto* particle = &obj; it != store.end() && particle; ++it) {
67  std::swap(it->particle, particle);
68  std::swap(it->result, result);
69  std::swap(it->extra, extra);
70  }
71  }
72 
73  private:
74  const std::function<F(const T&)> compare;
76 
77  const unsigned total;
78  unsigned num_filled = 0;
79  };
80 
81  }
82 }
83 
84 #endif