|
#include <iostream> |
|
#include <string> |
|
|
|
struct DefaultSlotKey; |
|
|
|
template <class Type, class Key = DefaultSlotKey> |
|
class Slot |
|
{ |
|
public: |
|
std::shared_ptr<Type> doGet() const |
|
{ |
|
return value_; |
|
} |
|
|
|
void doSet(const std::shared_ptr<Type> &value) |
|
{ |
|
value_ = value; |
|
} |
|
|
|
private: |
|
std::shared_ptr<Type> value_; |
|
}; |
|
|
|
template<class... Slots> |
|
class Repository : private Slots... { |
|
public: |
|
template <class Type, class Key = DefaultSlotKey> |
|
std::shared_ptr<Type> get() |
|
{ |
|
static_assert(std::is_base_of<Slot<Type, Key>, Repository<Slots...>>::value, |
|
"Please ensure that this type or this key exists in this repository"); |
|
return Slot<Type, Key>::doGet(); |
|
} |
|
|
|
template <class Type, class Key = DefaultSlotKey> |
|
void set(const std::shared_ptr<Type>& value) |
|
{ |
|
static_assert(std::is_base_of<Slot<Type, Key>, Repository<Slots...>>::value, |
|
"Please ensure that this type or this key exists in this repository"); |
|
Slot<Type, Key>::doSet(value); |
|
} |
|
|
|
template <class Type, class Key = DefaultSlotKey, class ...Args> |
|
void emplace(Args&&... args) |
|
{ |
|
static_assert(std::is_base_of<Slot<Type, Key>, Repository<Slots...>>::value, |
|
"Please ensure that this type or this key exists in this repository"); |
|
Slot<Type, Key>::doSet(std::make_shared<Type>(std::forward<Args>(args)...)); |
|
} |
|
|
|
template <class Type, class Key = DefaultSlotKey> |
|
auto getWatcher() -> decltype(std::declval<Slot<Type, Key>>().doGetWatcher()) |
|
{ |
|
return Slot<Type, Key>::doGetWatcher(); |
|
} |
|
}; |
|
|
|
// Incomplete types used as compile-time keys. |
|
struct Key1; |
|
struct Key2; |
|
|
|
// Create a type for our repository. |
|
using MyRepository = Repository |
|
< |
|
Slot<int>, // Let's pick the type of our slots. |
|
Slot<std::string> |
|
>; |
|
|
|
int main() |
|
{ |
|
MyRepository myRepository; |
|
myRepository.emplace<std::string>("toto"); |
|
|
|
std::cout << *myRepository.get<std::string>(); |
|
|
|
|
|
return EXIT_SUCCESS; |
|
} |