如何使用可变参数模板解决这个问题

时间:2014-02-07 18:16:41

标签: c++ c++11 variadic-templates

我想写一个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版本。如何使用可变参数模板解决这个问题,以便代码在编译时扩展?

此致 托拜厄斯

P.S。:我知道创建代码本身仍然缺失,而IoC-Container还没有,但我需要Register功能才能开始。


这是一个完整的例子(根据答案修改),显示了IoC的作用:

http://pastebin.com/mFu5FSTF - 编译&amp;在Windows上与MingW一起运行。

(它应该可以工作 - 如果没有,将它分成IoC.h和main.cpp文件并删除包含在前面的//)

1 个答案:

答案 0 :(得分: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;
}

我在VC ++ 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定义中包含一堆指针)而不仅仅是类型,这有点奇怪,但我不知道这里的完整图片。