Я хочу написать вещь 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 и удалите//перед включением)
В вашем вопросе можно было бы немного разъяснить, на что вы пытаетесь (например, пример кода использования). Но вот краткая демонстрация того, как делать то, что вы выложили вариативным способом:
// 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, содержащее пучок указателей), а не только тип, но я не знаю полной картины здесь.