Skip to content

Instantly share code, notes, and snippets.

@Jiwan
Created February 3, 2016 21:19
Show Gist options
  • Save Jiwan/c1daf7a80ebeb166dc61 to your computer and use it in GitHub Desktop.
Save Jiwan/c1daf7a80ebeb166dc61 to your computer and use it in GitHub Desktop.

Revisions

  1. Jiwan created this gist Feb 3, 2016.
    83 changes: 83 additions & 0 deletions repository_base.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,83 @@
    #include <iostream>
    #include <string>

    struct DefaultSlotKey;

    template <class Type, class Key = DefaultSlotKey>
    class Slot
    {
    protected:
    Type& doGet()
    {
    return value_;
    }

    void doSet(const Type& value)
    {
    value_ = value;
    }

    template <class... Args>
    void doEmplace(Args&&... args)
    {
    value_ = Type(std::forward<Args>(args)...);
    }
    private:
    Type value_;
    };

    template <class... Slots>
    class Repository : private Slots...
    {
    public:
    template <class Type, class Key = DefaultSlotKey>
    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 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>::doEmplace(std::forward<Args>(args)...);
    }
    };

    // 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.set<std::string>("toto");
    myRepository.set(42);

    std::cout << myRepository.get<int>() << std::endl; // Print: "toto".
    std::cout << myRepository.get<std::string>() << std::endl; // Print: 42.

    myRepository.emplace<std::string>(4, 'a');
    std::cout << myRepository.get<std::string>() << std::endl; // Print: 42.

    return EXIT_SUCCESS;
    }