Как решить эту проблему с помощью шаблонов

0

Я хочу написать вещь IoC/DI. В настоящее время я пришел к следующему:

#ifndef IOC_H_INCLUDED
#define IOC_H_INCLUDED

#include <unordered_map>
#include <functional>
#include <typeinfo>
#include <string>

namespace IoC
{

    class Resolver
    {
    public:
        template <typename Itf, typename Class>
        void Register();

        template <typename Itf, typename Class, typename Arg1>
        void Register();

        template <typename T>
        T* Create();
    private:
        std::unordered_map<std::string,std::function<void*()>> m_creationFunctions;
    };

    template <typename Itf, typename Class>
    void Resolver::Register()
    {
        std::function<void*()> creator = [=](){ return new Class();};
        m_creationFunctions[std::string(typeid(Itf).name())]=creator;
    }

    template <typename Itf, typename Class, typename Arg1>
    void Resolver::Register()
    {
        std::function<void*()> creator = [=](){ return new Class(this->Create<Arg1>());};
        m_creationFunctions[std::string(typeid(Itf).name())]=creator;
    }

    template <typename T>
    T* Resolver::Create()
    {
        return nullptr;
    }
}

#endif // IOC_H_INCLUDED

Как вы можете видеть в приведенном выше коде, мне нужна одна версия Register для каждого числа аргументов конструктора. Как я могу решить это, используя вариативные шаблоны, чтобы код расширялся во время компиляции?

С уважением, Тобиас

PS: Я знаю, что сам код создания по-прежнему отсутствует, а IoC-Container еще не существует, но для начала мне нужна функция Register.


Вот полный пример (модифицированный в соответствии с ответом), который показывает, что делает IoC:

http://pastebin.com/mFu5FSTF - компилируется и работает с MingW в Windows.

(он должен работать - если это не так, отделите его в файле IoC.h & main.cpp и удалите//перед включением)

  • 0
    Вы сами пробовали использовать вариадические шаблоны?
  • 0
    Вы также можете показать, как будет выглядеть двухпараметрическая версия? Оттуда должно быть довольно легко обобщить это в variadic.
Показать ещё 3 комментария
Теги:
c++11
variadic-templates

1 ответ

3
Лучший ответ

В вашем вопросе можно было бы немного разъяснить, на что вы пытаетесь (например, пример кода использования). Но вот краткая демонстрация того, как делать то, что вы выложили вариативным способом:

// in class definition
template <typename Itf, typename Class, typename ...Args>
void Register();

// in implementation section
template <typename Itf, typename Class, typename ...Args>
void Resolver::Register()
{
    std::function<void*()> creator = [=](){ return new Class(this->Create<Args>()...);};
    m_creationFunctions[std::string(typeid(Itf).name())]=creator;
}

Я быстро проверил это со следующим на VС++ 12, и все выглядело хорошо:

struct TestStruct {
  TestStruct(int * a, int * b, int * c) 
    : a_(a), b_(b), c_(c) {
  }
  int * a_;
  int * b_;
  int * c_;
};

// ...

IoC::Register testRegister;
testRegister.Register<int, TestStruct, int, int, int>();

Немного странно, что ваш Create возвращает указатели (следовательно, определение TestStruct, содержащее пучок указателей), а не только тип, но я не знаю полной картины здесь.

  • 0
    полная картина еще не на месте. Я просто предполагаю, что указатель сможет хранить классы внутри IoC-контейнера, который управляет временем жизни.
  • 0
    Спасибо, это работает.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню