Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在C+中正确创建带有可变模板的显式参数转发函数+;11_C++_C++11_Factory_Variadic Templates_Variadic Functions - Fatal编程技术网

C++ 如何在C+中正确创建带有可变模板的显式参数转发函数+;11

C++ 如何在C+中正确创建带有可变模板的显式参数转发函数+;11,c++,c++11,factory,variadic-templates,variadic-functions,C++,C++11,Factory,Variadic Templates,Variadic Functions,我正在开发一个类,该类允许您将具有公共基类型的类型动态注册到键,然后基于键动态构造该类型的实例。下面是它现在的样子: template<class Key, class Base> class TypeRegistry { private: FunctionRegistry<Key, Base*> m_registry; template<class Derived> static Base* make() {

我正在开发一个类,该类允许您将具有公共基类型的类型动态注册到键,然后基于键动态构造该类型的实例。下面是它现在的样子:

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;
    }
};
现在,我的问题是使用可变模板扩展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;
    }
};
模板
类类型注册表
{
私人:
功能注册表m_注册表;
样板
静基座*制造(???)
{
返回新的导出(??);
}
公众:
样板
无效寄存器类型(常数键和键)
{
m_注册表。注册功能(键和make);
}
样板
Base*make_类型(常量键和键,已确定的args和args)常量
{
自动生成器=m_注册表。获取函数(键);
如果(制造商)返回制造商(标准::转发(参数)…);
否则返回空ptr;
}
};

问题是,我不知道如何正确地为make()函数设置模板。大概它只需要将
ConstructorArgs…
作为它的参数,这样就可以在
FunctionRegistry
中正确注册它,但是我如何确保所有参数都正确转发(右值vs左值)到
派生的
构造函数?

因为您没有输入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();
}
#包括
#包括
结构基
{
虚拟~Abase(){}
虚拟空心条()=0;
};
结构A:Abase
{
A(int g,float h):Abase(),A(g),b(h)
{
}
虚拟~A(){}
虚拟空心条()
{

std::你听说过完美转发吗?是的,我正在做它make_type。问题是当你必须显式地实例化函数模板时(如
register_type
),而不是编译器为你做时(如
make_type
),不清楚如何做完美转发完美转发需要模板参数推导,并且没有函数指针模板。因此,您注册的每个类型都使用完全相同的参数构造?这是一个要求,是的。
#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();
}