Empirical
Trait.h
Go to the documentation of this file.
1 // This file is part of Empirical, https://github.com/devosoft/Empirical
2 // Copyright (C) Michigan State University, 2016.
3 // Released under the MIT Software license; see doc/LICENSE
4 //
5 //
6 // The TraitDef class maintains a category of measuments about another class.
7 //
8 // Each trait is associated with a name, a description, and a type. Instance of that
9 // trait are of type TraitValue. A TraitManager contains information about a group of
10 // related traits, and a TraitSet is a set of TraitValues.
11 
12 #ifndef EMP_TRAIT_H
13 #define EMP_TRAIT_H
14 
15 #include <string>
16 #include <tuple>
17 #include <type_traits>
18 #include <vector>
19 
20 #include "../base/assert.h"
21 #include "../tools/functions.h"
22 #include "../meta/meta.h"
23 
24 namespace emp {
25 
26  template <typename TRAIT_TYPE> struct TraitKey {
27  int index;
28  TraitKey(int _index) : index(_index) { ; }
29  };
30 
31  template <typename TRAIT_TYPE>
32  class TraitDef {
33  private:
34  const std::string name;
35  const std::string desc;
36  const TRAIT_TYPE default_val;
37  const int index;
38 
39  public:
40  TraitDef(const std::string & _name, const std::string & _desc, const TRAIT_TYPE & _default_val,
41  int _index)
42  : name(_name), desc(_desc), default_val(_default_val), index(_index)
43  { ; }
44  ~TraitDef() { ; }
45 
46  const std::string & GetName() const { return name; }
47  const std::string & GetDesc() const { return desc; }
48  const TRAIT_TYPE & GetDefault() const { return default_val; }
49  int GetIndex() const { return index; }
50  TraitKey<TRAIT_TYPE> GetKey() const { return index; }
51  };
52 
53  template <typename... TRAIT_TYPES> class TraitManager;
54 
55  template <typename... TRAIT_TYPES>
56  class TraitSet {
57  friend class TraitManager<TRAIT_TYPES...>;
58  private:
59  std::tuple< std::vector<TRAIT_TYPES>... > type_sets;
60 
61  // Add in a new trait (with value) to the appropriate type set.
62  template <typename IN_TYPE>
63  void PushTrait(const IN_TYPE & in_trait) {
64  constexpr int type_id = emp::get_type_index<IN_TYPE, TRAIT_TYPES...>();
65  static_assert(type_id >= 0, "Unhandled type provided to TraitSet::PushTrait()");
66  std::get<type_id>(type_sets).push_back(in_trait);
67  }
68 
69  // Get set (vector of entries) associated with the given type.
70  template <typename IN_TYPE>
71  std::vector<IN_TYPE> & GetTypeSet() {
72  constexpr int type_id = emp::get_type_index<IN_TYPE, TRAIT_TYPES...>();
73  static_assert(type_id >= 0, "Unknown type provided to TraitSet::GetTypeSet()");
74  return std::get< type_id >(type_sets);
75  }
76 
77  public:
78  TraitSet(const TraitManager<TRAIT_TYPES...> & tm); // Defined after TraitManager.
79 
80  // Access a specific trait value by passing in its definition.
81  template <typename IN_TYPE>
82  const IN_TYPE & Get(const TraitKey<IN_TYPE> & in_key) const {
83  constexpr int type_id = emp::get_type_index<IN_TYPE, TRAIT_TYPES...>();
84  static_assert(type_id >= 0, "Unknown type provided to TraitSet::Get() const");
85  return std::get<type_id>(type_sets)[in_key.GetIndex()];
86  }
87 
88  template <typename IN_TYPE>
89  IN_TYPE & Get(const TraitKey<IN_TYPE> & in_key) {
90  constexpr int type_id = emp::get_type_index<IN_TYPE, TRAIT_TYPES...>();
91  static_assert(type_id >= 0, "Unknown type provided to TraitSet::Get()");
92  return std::get<type_id>(type_sets)[in_key.GetIndex()];
93  }
94  };
95 
96  template <typename... TRAIT_TYPES>
97  class TraitManager {
98  friend class TraitSet<TRAIT_TYPES...>;
99  private:
100  // A group of trait definitions must be created for each type handled.
101  std::tuple< std::vector< TraitDef<TRAIT_TYPES> >... > trait_groups;
102  int num_traits;
103  TraitSet<TRAIT_TYPES...> default_trait_set;
104 
105  static const int num_types = sizeof...(TRAIT_TYPES);
106 
107  // Helper Functions:
108 
109  // Return a constant indicating the position of a given type in the tuple.
110  template <typename BASE_TYPE>
111  constexpr static int GetTraitID() {
112  return emp::get_type_index<BASE_TYPE, TRAIT_TYPES...>();
113  }
114 
115  // Return the vector of traits for the given type (const version).
116  template <typename IN_TYPE>
117  const std::vector< TraitDef<IN_TYPE> > & GetTraitGroup() const {
118  static_assert(GetTraitID<IN_TYPE>() >= 0,
119  "Unknown type provided to TraitManager::GetTraitGroup() const");
120  return std::get< GetTraitID<IN_TYPE>() >(trait_groups);
121  }
122 
123  // Return the vector of traits for the given type.
124  template <typename IN_TYPE>
125  std::vector< TraitDef<IN_TYPE> > & GetTraitGroup() {
126  static_assert(GetTraitID<IN_TYPE>() >= 0,
127  "Unknown type provided to TraitManager::GetTraitGroup()");
128  return std::get< GetTraitID<IN_TYPE>() >(trait_groups);
129  }
130 
131  // Base Case...
132  template <typename CUR_TYPE>
133  void SetDefaultsByType(TraitSet<TRAIT_TYPES...> & trait_set) const {
134  // Get the relevant vectors for the current type.
135  const std::vector< TraitDef<CUR_TYPE> > & cur_group = GetTraitGroup<CUR_TYPE>();
136  std::vector<CUR_TYPE> & type_set = trait_set.template GetTypeSet<CUR_TYPE>();
137 
138  // Set all of the values in type_set
139  type_set.resize(0);
140  for (const TraitDef<CUR_TYPE> & cur_def : cur_group) {
141  type_set.push_back(cur_def.GetDefault());
142  }
143  }
144 
145  template <typename FIRST_TYPE, typename SECOND_TYPE, typename... OTHER_TYPES>
146  void SetDefaultsByType(TraitSet<TRAIT_TYPES...> & trait_set) const {
147  SetDefaultsByType<FIRST_TYPE>(trait_set);
148 
149  // And recurse through the other types.
150  SetDefaultsByType<SECOND_TYPE, OTHER_TYPES...>(trait_set);
151  }
152 
153  public:
154  TraitManager() : num_traits(0), default_trait_set(*this) { ; }
156 
157  static int GetNumTypes() { return num_types; }
158 
159  int GetNumTraits() const { return num_traits; }
160  template <typename IN_TYPE> int GetNumTraitsOfType() const {
161  return (int) GetTraitGroup<IN_TYPE>().size();
162  }
163 
164  // Lookup a trait by its type and index.
165  template <typename IN_TYPE>
167  std::vector< TraitDef<IN_TYPE> > & cur_group = GetTraitGroup<IN_TYPE>();
168  emp_assert(index >= 0 && index < (int) cur_group.size());
169  return cur_group[index];
170  }
171 
172  // Lookup a trait by its type and index.
173  template <typename IN_TYPE>
175  std::vector< TraitDef<IN_TYPE> > & cur_group = GetTraitGroup<IN_TYPE>();
176  return cur_group[key.GetIndex()];
177  }
178 
179  template <typename IN_TYPE>
180  const TraitDef<IN_TYPE> & AddTrait(const std::string & _name, const std::string & _desc,
181  const IN_TYPE & _default_val) {
182  std::vector< TraitDef<IN_TYPE> > & cur_group = GetTraitGroup<IN_TYPE>();
183  const int trait_index = (int) cur_group.size();
184  cur_group.push_back( TraitDef<IN_TYPE>(_name, _desc, _default_val, trait_index) );
185  num_traits++;
186  return cur_group[trait_index];
187  }
188 
189  void SetDefaults(TraitSet<TRAIT_TYPES...> & trait_set) const {
190  SetDefaultsByType<TRAIT_TYPES...>(trait_set);
191  }
192  };
193 
194 
195  template <typename... TRAIT_TYPES>
197  tm.SetDefaults(*this);
198  }
199 
200 }
201 
202 #endif
TraitManager()
Definition: Trait.h:154
~TraitManager()
Definition: Trait.h:155
IN_TYPE & Get(const TraitKey< IN_TYPE > &in_key)
Definition: Trait.h:89
Definition: Trait.h:26
Definition: Trait.h:32
void SetDefaults(TraitSet< TRAIT_TYPES... > &trait_set) const
Definition: Trait.h:189
TraitSet()
Definition: Trait.h:112
const TraitDef< IN_TYPE > & GetTraitDef(int index)
Definition: Trait.h:166
TraitDef(const std::string &_name, const std::string &_desc, const TRAIT_TYPE &_default_val, int _index)
Definition: Trait.h:40
static int GetNumTypes()
Definition: Trait.h:157
~TraitDef()
Definition: Trait.h:44
TraitKey< TRAIT_TYPE > GetKey() const
Definition: Trait.h:50
const TraitDef< IN_TYPE > & GetTraitDef(TraitKey< IN_TYPE > key)
Definition: Trait.h:174
Definition: Trait.h:53
const TraitDef< IN_TYPE > & AddTrait(const std::string &_name, const std::string &_desc, const IN_TYPE &_default_val)
Definition: Trait.h:180
int index
Definition: Trait.h:27
If we are in emscripten, make sure to include the header.
Definition: array.h:37
const std::string & GetDesc() const
Definition: Trait.h:47
#define emp_assert(...)
Definition: assert.h:199
constexpr int get_type_index()
Definition: meta.h:70
const TRAIT_TYPE & GetDefault() const
Definition: Trait.h:48
const IN_TYPE & Get(const TraitKey< IN_TYPE > &in_key) const
Definition: Trait.h:82
int GetNumTraitsOfType() const
Definition: Trait.h:160
A TraitSet houses a collection of traits and can trigger them to all be evaluated at once...
Definition: Trait.h:103
const std::string & GetName() const
Definition: Trait.h:46
TraitKey(int _index)
Definition: Trait.h:28
int GetIndex() const
Definition: Trait.h:49
int GetNumTraits() const
Definition: Trait.h:159