14 #include <unordered_map>
26 {
return h ==
typeid(T).hash_code(); }
28 template<
typename T,
typename U,
typename... Args>
30 {
return is_valid_hash<T>(h) ||
is_valid_hash<U, Args...>(h); }
34 {
return name == type_name<T>(); }
36 template<
typename T,
typename U,
typename... Args>
38 {
return is_valid_name<T>(name) ||
is_valid_name<U, Args...>(name); }
47 template<
typename C,
typename RetT,
typename... Args>
50 using fn_t = std::function<RetT(Args...)>;
54 template<
typename C,
typename RetT,
typename... Args>
57 using fn_t = std::function<RetT(Args...)>;
69 using decay_t =
typename std::decay<T>::type;
71 using type =
typename std::conditional<is_arithmetic, decay_t, T>::type;
75 template<
typename T,
typename =
void>
82 struct Allocator<T, typename T::eigen_aligned_operator_new_marker_type> :
public Eigen::aligned_allocator<T>
139 inline bool has(
const std::string &
name)
const noexcept {
return datas_.find(
name) != datas_.end(); }
144 inline std::vector<std::string>
keys() const noexcept
146 std::vector<std::string> out;
147 out.reserve(datas_.size());
148 for(
const auto & d : datas_) { out.push_back(d.first); }
164 {
return const_cast<T &
>(get_<T>(
name)); }
169 {
return get_<T>(
name); }
181 auto it = datas_.find(
name);
182 if(it != datas_.end()) { data = safe_cast<T>(it->second,
name); }
195 const T &
get(
const std::string &
name,
const T & defaultValue)
const
197 auto it = datas_.find(
name);
198 if(it != datas_.end()) {
return safe_cast<T>(it->second,
name); }
212 { get<T>(
name) = data; }
227 template<
typename T,
typename... ArgsT,
typename... Args>
228 T &
make(
const std::string &
name, Args &&... args)
230 auto & data = datas_[
name];
232 data.allocate<T>(name_,
name);
233 new(data.buffer.get()) T(std::forward<Args>(args)...);
234 return data.setup<T, ArgsT...>();
251 return make<fn_t>(
name, fn_t(fn));
262 template<
typename T,
typename... ArgsT,
typename... Args>
265 auto & data = datas_[
name];
267 data.allocate<T>(name_,
name);
268 new(data.buffer.get()) T{std::forward<Args>(args)...};
269 return data.setup<T, ArgsT...>();
289 template<
typename RetT,
290 typename... FuncArgsT,
292 typename std::enable_if<
sizeof...(FuncArgsT) ==
sizeof...(ArgsT)
293 && !std::is_same<std::tuple<FuncArgsT...>, std::tuple<ArgsT...>>
::value,
295 RetT
call(
const std::string &
name, ArgsT &&... args)
const
296 {
return safe_call<RetT, FuncArgsT...>(
name, std::forward<ArgsT>(args)...); }
316 template<
typename RetT = void,
typename... ArgsT>
317 RetT
call(
const std::string &
name, ArgsT &&... args)
const
318 {
return safe_call<RetT, typename internal::args_t<ArgsT>::type...>(
name, std::forward<ArgsT>(args)...); }
326 auto it = datas_.find(
name);
327 if(it == datas_.end())
329 log::error(
"[{}] Failed to remove element \"{}\" (element does not exist)", name_,
name);
338 inline void clear() noexcept { datas_.clear(); }
343 inline const std::string &
name() const noexcept {
return name_; }
356 Data(
const Data &) =
delete;
358 Data(Data &&) =
default;
362 std::unique_ptr<uint8_t[]> buffer;
364 std::string (*type)();
366 bool (*same)(std::size_t);
368 bool (*same_name)(
const std::string &);
370 void (*destroy)(Data &);
374 if(buffer) { destroy(*
this); }
378 void allocate(
const std::string & name_,
const std::string &
name)
381 buffer.reset(
reinterpret_cast<uint8_t *
>(internal::Allocator<T>().allocate(1)));
384 template<
typename T,
typename... ArgsT>
387 this->type = &type_name<T>;
390 this->destroy = [](Data &
self)
392 T * p =
reinterpret_cast<T *
>(
self.buffer.release());
394 internal::Allocator<T>().deallocate(p, 1);
396 return *(
reinterpret_cast<T *
>(buffer.get()));
401 const T & safe_cast(
const Data & data,
const std::string &
name)
const
403 if(!data.same(
typeid(T).hash_code()) && !data.same_name(type_name<T>()))
406 "[{} Object for key \"{}\" does not have the same type as the stored type. Stored {} but requested {}.",
407 name_,
name, data.type(), type_name<T>());
409 return *(
reinterpret_cast<T *
>(data.buffer.get()));
412 template<
typename RetT,
typename... FuncArgsT,
typename... ArgsT>
413 RetT safe_call(
const std::string &
name, ArgsT &&... args)
const
415 const auto & data = get_data(
name);
416 using fn_t = std::function<RetT(FuncArgsT...)>;
417 if(!data.same(
typeid(fn_t).hash_code()) && !data.same_name(type_name<fn_t>()))
420 "requested one. Stored {} but requested {}",
421 name_,
name, data.type(), type_name<fn_t>());
423 auto & fn = *(
reinterpret_cast<fn_t *
>(data.buffer.get()));
424 return fn(std::forward<ArgsT>(args)...);
428 const T & get_(
const std::string &
name)
const
429 {
return safe_cast<T>(get_data(
name),
name); }
431 inline const Data & get_data(
const std::string &
name)
const
433 const auto it = datas_.find(
name);
439 std::unordered_map<std::string, Data> datas_;
440 std::string name_ =
"DataStore";
std::optional< Eigen::VectorXd > value
bool is_valid_hash(std::size_t h)
Definition: DataStore.h:25
bool is_valid_name(const std::string &name)
Definition: DataStore.h:33
void error_and_throw(const S &format, Args &&... args)
Definition: logging.h:40
void error(const S &format, Args &&... args)
Definition: logging.h:65
Generic data store.
Definition: DataStore.h:125
DataStore & operator=(const DataStore &)=delete
DataStore(const DataStore &)=delete
bool has(const std::string &name) const noexcept
Checks whether an object is in the datastore.
Definition: DataStore.h:139
void remove(const std::string &name) noexcept
Removes an object from the datastore.
Definition: DataStore.h:324
std::vector< std::string > keys() const noexcept
Returns all objects in the datastore.
Definition: DataStore.h:144
void assign(const std::string &name, const T &data)
Copies an object to an existing datastore object.
Definition: DataStore.h:211
void get(const std::string &name, T &data)
Assign value from the datastore if it exists, leave value unchanged otherwise.
Definition: DataStore.h:179
const T & get(const std::string &name) const
const variant of get
Definition: DataStore.h:168
RetT call(const std::string &name, ArgsT &&... args) const
Calls a function that was registered in the datastore and returns this call result.
Definition: DataStore.h:295
const T & get(const std::string &name, const T &defaultValue) const
Gets a value from the datastore if it exists or a default value otherwise.
Definition: DataStore.h:195
void clear() noexcept
Remove all entries in the datastore.
Definition: DataStore.h:338
DataStore & operator=(DataStore &&)=default
T & make(const std::string &name, Args &&... args)
Creates an object on the datastore and returns a reference to it.
Definition: DataStore.h:228
DataStore(DataStore &&)=default
RetT call(const std::string &name, ArgsT &&... args) const
Calls a function that was registered in the datastore and returns this call result.
Definition: DataStore.h:317
T & make_initializer(const std::string &name, Args &&... args)
Creates an object on the datastore using list initialization and returns a reference to it.
Definition: DataStore.h:263
void name(const std::string &name) noexcept
Sets this datastore's name.
Definition: DataStore.h:350
auto make_call(const std::string &name, T fn) -> typename internal::lambda_traits< T >::fn_t &
Creates an object on the datastore and returns a reference to it.
Definition: DataStore.h:248
T & get(const std::string &name)
Get a reference to an object on the datastore.
Definition: DataStore.h:163
const std::string & name() const noexcept
Name of this datastore.
Definition: DataStore.h:343
Definition: DataStore.h:77
Definition: DataStore.h:68
typename std::conditional< is_arithmetic, decay_t, T >::type type
Definition: DataStore.h:71
typename std::decay< T >::type decay_t
Definition: DataStore.h:69
static constexpr bool is_arithmetic
Definition: DataStore.h:70
std::function< RetT(Args...)> fn_t
Definition: DataStore.h:50
std::function< RetT(Args...)> fn_t
Definition: DataStore.h:57
Definition: DataStore.h:43