Вопрос

I want to write a IoC/DI thing. I currently came up with the following:

#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

As you can see in the code above, I need one version of Register for each number of constructor arguments. How can I solve this using variadic templates so that the code expands at compile time?

Regards Tobias

P.S.: I know that the creation code itself is still missing, and the IoC-Container is not yet there, but I need the Register functionality to get started.


Here's a complete example (modified according to the answer) that shows what IoC does:

http://pastebin.com/mFu5FSTF - compiles & runs with MingW on Windows.

(it should work - if it doesn't, separate it into IoC.h & main.cpp file and remove the // in front of the include)

Это было полезно?

Решение

Your question could use a little clarification on whats being attempted (sample use code, for instance.) But here's a quick demo on how to do what you've laid out in a variadic way:

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

I tested this quickly with the following on VC++12 and everything looked okay:

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>();

It's a little odd that your Create returns pointers (hence the TestStruct definition holding a bunch of pointers) rather than just the type, but I don't know the complete picture here.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top