10 #ifndef smtk_plugin_Registry_h
11 #define smtk_plugin_Registry_h
13 #include "smtk/common/CompilerInformation.h"
15 #include "smtk/CoreExports.h"
20 #include <type_traits>
26 #include "smtk/plugin/Sentinel.h"
65 template<
typename Registrar,
typename Manager>
69 static std::true_type testRegisterTo(
70 decltype(std::declval<Registrar>().registerTo(std::declval<std::shared_ptr<X>>()))*);
72 static std::false_type testRegisterTo(...);
75 static std::true_type testUnregisterFrom(
76 decltype(std::declval<Registrar>().unregisterFrom(std::declval<std::shared_ptr<X>>()))*);
78 static std::false_type testUnregisterFrom(...);
82 decltype(testRegisterTo<Manager>(
nullptr)),
83 decltype(testUnregisterFrom<Manager>(
nullptr))>::value,
84 "Registrar must be able to both register and unregister from a manager.");
87 using type = decltype(testRegisterTo<Manager>(
nullptr));
97 template<
typename Registrar,
typename Manager>
98 std::size_t& operator[](
Manager* manager)
100 return this->operator[](
101 std::make_pair(manager, std::type_index(
typeid(Registrar)).hash_code()));
108 std::size_t& operator[](
const std::pair<void*, std::size_t>& key);
122 template<
typename Registrar,
typename Manager,
typename Choice>
125 template<
typename Registrar,
typename Manager>
133 bool contains(
const std::shared_ptr<M>&)
const
139 template<
typename Registrar,
typename Manager>
146 if (ManagerCount::instance().
operator[]<Registrar,
Manager>(manager.get())++ == 0)
148 Registrar().registerTo(m_Manager);
155 m_Manager && --ManagerCount::instance().
operator[]<Registrar,
Manager>(m_Manager.get()) == 0)
157 Registrar().unregisterFrom(m_Manager);
162 bool contains(
const std::shared_ptr<M>&)
const
167 bool contains(
const std::shared_ptr<Manager>& manager)
const {
return manager == m_Manager; }
170 std::shared_ptr<Manager> m_Manager;
178 template<
typename Registrar>
182 static typename R::Dependencies deps(
typename R::Dependencies*);
185 static std::tuple<> deps(...);
188 struct is_tuple : std::false_type
192 template<
typename... T>
193 struct is_tuple<std::tuple<T...>> : std::true_type
198 using type = decltype(deps<Registrar>(
nullptr));
200 static_assert(is_tuple<type>::value,
"Registrar dependencies must be given as a std::tuple.");
205 template<
typename... Registrars>
208 template<
typename Registrar,
typename... Registrars>
215 using type = decltype(std::tuple_cat(
216 std::declval<
typename Dependencies<Registrar>::type>(),
233 using type = std::tuple<>;
240 using type = std::tuple<>;
246 template<
typename Registrar>
266 for (
auto it = m_registries.begin(); it != m_registries.end(); ++it)
273 std::vector<RegistryBase*> m_registries;
295 template<
typename Registrar,
typename Manager,
typename... T>
298 MaybeRegister<Registrar, Manager, typename detail::RegistersTo<Registrar, Manager>::type>
303 Registry(
const std::shared_ptr<Manager>& manager,
const std::shared_ptr<T>&... managers)
305 MaybeRegister<Registrar, Manager, typename detail::RegistersTo<Registrar, Manager>::type>(
311 this->registerDependencies<0, typename detail::AllDependencies<Registrar>::type>(
312 manager, std::forward<const std::shared_ptr<T>&>(managers)...);
316 bool contains(
const std::shared_ptr<M>& m)
318 auto tmp =
dynamic_cast<
320 return tmp !=
nullptr && tmp->contains(m);
325 typedef int DoNotRegisterDependencies;
328 DoNotRegisterDependencies,
329 const std::shared_ptr<Manager>& manager,
330 const std::shared_ptr<T>&... managers)
332 MaybeRegister<Registrar, Manager, typename detail::RegistersTo<Registrar, Manager>::type>(
341 template<std::
size_t I,
typename Tuple>
342 inline typename std::enable_if<I != std::tuple_size<Tuple>::value>::type registerDependencies(
343 const std::shared_ptr<Manager>& manager,
344 const std::shared_ptr<T>&... managers)
346 m_registries.push_back(
new Registry<
typename std::tuple_element<I, Tuple>::type,
Manager, T...>(
347 0, manager, std::forward<
const std::shared_ptr<T>&>(managers)...));
348 return registerDependencies<I + 1, Tuple>(
349 manager, std::forward<
const std::shared_ptr<T>&>(managers)...);
352 template<std::
size_t I,
typename Tuple>
353 inline typename std::enable_if<I == std::tuple_size<Tuple>::value>::type registerDependencies(
354 const std::shared_ptr<Manager>&,
355 const std::shared_ptr<T>&...)
366 MaybeRegister<Registrar, Manager, typename detail::RegistersTo<Registrar, Manager>::type>
370 Registry(
const std::shared_ptr<Manager>& manager,
const std::shared_ptr<T>&... managers)
372 MaybeRegister<Registrar,
Manager, typename detail::RegistersTo<Registrar,
Manager>::type>(
374 ,
Registry<Registrar, T...>(managers...)
376 this->registerDependencies<0, typename detail::AllDependencies<Registrar>::type>(
377 manager, std::forward<const std::shared_ptr<T>&>(managers)...);
380 ~Registry()
override =
default;
383 bool contains(
const std::shared_ptr<M>& m)
385 auto tmp =
dynamic_cast<
386 detail::MaybeRegister<Registrar, M, typename detail::RegistersTo<Registrar, M>::type
>*>(
this);
387 return tmp !=
nullptr && tmp->contains(m);
390 Registry(
int,
const std::shared_ptr<Manager>& manager,
const std::shared_ptr<T>&... managers)
392 MaybeRegister<Registrar,
Manager, typename detail::RegistersTo<Registrar,
Manager>::type>(
394 , Registry<Registrar, T...>(managers...)
399 template<std::
size_t I,
typename Tuple>
400 inline typename std::enable_if<I != std::tuple_size<Tuple>::value>::type registerDependencies(
401 const std::shared_ptr<Manager>& manager,
402 const std::shared_ptr<T>&... managers)
404 m_registries.push_back(
new Registry<
typename std::tuple_element<I, Tuple>::type,
Manager, T...>(
405 0, manager, std::forward<
const std::shared_ptr<T>&>(managers)...));
406 return registerDependencies<I + 1, Tuple>(
407 manager, std::forward<
const std::shared_ptr<T>&>(managers)...);
410 template<std::
size_t I,
typename Tuple>
411 inline typename std::enable_if<I == std::tuple_size<Tuple>::value>::type registerDependencies(
412 const std::shared_ptr<Manager>&,
413 const std::shared_ptr<T>&...)
419 template<
typename Registrar>
420 class Registry<Registrar, detail::Sentinel> :
public RegistryBase
423 Registry() =
default;
425 ~Registry()
override =
default;
430 template<
typename Registrar,
typename...
Manager>
431 static Registry<Registrar,
Manager...> addToManagers(
const std::shared_ptr<Manager>&... manager)
433 return Registry<Registrar,
Manager...>(manager...);