我正在开发一个类,它允许您动态地将具有公共基类型的类型注册到键,然后基于键动态构造该类型的实例。这就是现在的样子:
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
中正确注册,但是如何确保所有参数都被正确转发(rvalue vs lvalue)到Derived
构造函数?
答案 0 :(得分: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();
}