1

我正在研究一个类,它允许您将具有公共基类型的类型动态注册到键,然后根据键动态构造该类型的实例。这是它现在的样子:

template<class Key, class Base>
class TypeRegistry
{
private:
    FunctionRegistry<Key, Base*> m_registry;

    template<class Derived>
    static Base* make()
    {
        return new Derived();
    }

public:
    template<class Derived>
    void register_type(const Key& key)
    {
        m_registry.register_function(key, &make<Derived>);
    }

    Base* make_type(const Key& key) const
    {
        auto maker = m_registry.get_function(key);
        if(maker) return maker();
        else return nullptr;
    }
};

该类FunctionRegistry有这个接口:

template<class Key, class Ret, class... Args>
class FunctionRegistry
{
public:
    typedef Ret (*function_type)(Args...);

    //register a key and function pointer
    void register_function(const Key& key, function_type func);

    //get a function pointer, or nullptr if the key is not registered
    function_type get_function(const Key& key) const;
};

现在,我的问题是关于使用可变参数模板扩展 TypeRegistry 以支持构造函数参数。我不知道我应该执行 TypeRegistry::make 函数。这是我所希望的:

template<class Key, class Base, class... ConstructorArgs>
class TypeRegistry
{
private:
    FunctionRegistry<Key, Base*, ConstructorArgs...> m_registry;

    template<class Derived, ???>
    static Base* make(???)
    {
        return new Derived(???);
    }

public:
    template<class Derived>
    void register_type(const Key& key)
    {
        m_registry.register_function(key, &make<Derived, ???>);
    }

    template<class... DeterminedArgs>
    Base* make_type(const Key& key, DeterminedArgs&&... args) const
    {
        auto maker = m_registry.get_function(key);
        if(maker) return maker(std::forward<DeterminedArgs>(args)...);
        else return nullptr;
    }
};

问题是,我不知道如何正确模板化 make() 函数。大概它必须ConstructorArgs...作为它的参数,以便它可以在 中正确注册FunctionRegistry,但是我如何确保所有参数都正确转发(右值与左值)到Derived构造函数?

4

1 回答 1

0

由于您没有放置 FunctionRegistry 的定义,我无法测试它。现在我创建了一个真实的例子(它可以编译)并在哪里解决了这些问题。最大的问题之一是您试图将指向成员函数的指针传递给函数指针。因此,您必须创建TypeRegistry::make一个静态方法。

所以,这里是:

#include <iostream>
#include <utility>

struct Abase
{
    virtual ~Abase(){}
    virtual void bar()=0;
};
struct A : Abase
{
    A(int g,float h) : Abase(), a(g),b(h)
    {
    }
    virtual ~A(){}

    virtual void bar()
    {
        std::cout<<a<<b<<std::endl;
    }
    int a;float b;
};
Abase* foo(int&& v,float&& b)
{
    return new A(v,b);
}

template<class Key, class Ret, class... Args>
class FunctionRegistry
{
public:
    typedef Ret (*function_type)(Args...);

    //register a key and function pointer
    void register_function(const Key& key, function_type func)
    {}

    //get a function pointer, or nullptr if the key is not registered
    function_type get_function(const Key& key) const
    {
        (void)key;
        return foo;
    }
};

template<class Key, class Base, class... ConstructorArgs>
class TypeRegistry
{
private:
    FunctionRegistry<Key, Base*, ConstructorArgs&&...> m_registry;

    template<class Derived>
    static Base* make(ConstructorArgs&&... args)
    {
        return new Derived(std::forward<ConstructorArgs>(args)...);
    }

public:
    template<class Derived>
    void register_type(const Key& key)
    {
        m_registry.register_function(key, &make<Derived> );
    }

    Base* make_type(const Key& key, ConstructorArgs&&... args) const
    {
        auto maker = m_registry.get_function(key);
        if(maker) return maker(std::forward<ConstructorArgs>(args)...);
        else return nullptr;
    }
};


int main()
{
    TypeRegistry< int, Abase, int, float > tr;

    tr.register_type< A >( 5 );

    auto a = tr.make_type( 5, 3, 5.3f );
    a->bar();
}
于 2013-10-14T06:24:34.463 回答