| 
          #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; | 
        
        
           | 
          } |