Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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
Templates C++;:可以调用任何构造函数的通用工厂?_Templates_C++11_Factory_Type Erasure - Fatal编程技术网

Templates C++;:可以调用任何构造函数的通用工厂?

Templates C++;:可以调用任何构造函数的通用工厂?,templates,c++11,factory,type-erasure,Templates,C++11,Factory,Type Erasure,我正在尝试编写一个factory类,它将有一个如下所示的标准接口: Register<MyBase, MyDerived> g_regDerived("myderived"); // register to factory 这里的问题是,一旦删除创建对象的类型,就不能再传递任意模板转发参数,因为需要通过虚拟函数传递它们 这个问题的答案是: 讨论了一些类似的问题,但答案是通过一个特定于每个派生类的函数。我想直接使用类构造函数,而不必编写create()函数。我不知道您为什么不喜欢

我正在尝试编写一个factory类,它将有一个如下所示的标准接口:

Register<MyBase, MyDerived> g_regDerived("myderived");  // register to factory
这里的问题是,一旦删除创建对象的类型,就不能再传递任意模板转发参数,因为需要通过虚拟函数传递它们

这个问题的答案是:


讨论了一些类似的问题,但答案是通过一个特定于每个派生类的函数。我想直接使用类构造函数,而不必编写
create()
函数。

我不知道您为什么不喜欢编写
create()
函数。这里是我实现的一个

#include <iostream>
#include <utility>

using namespace std;

class C
{
public:
    virtual char const* whoAmI() const = 0;
};

class A : public C
{
public:
    A(int a1)
    {
        cout << "A(" << a1 << ")" << endl;
    }
    
    A(float a1)
    {
        cout << "A(" << a1 << ")" << endl;
    }
    
    virtual char const* whoAmI() const override
    {
        return "A";
    }
};

class B : public C
{
public:
    B(int a1)
    {
        cout << "B(" << a1 << ")" << endl;
    }
    
    B(float a1)
    {
        cout << "B(" << a1 << ")" << endl;
    }

    virtual char const* whoAmI() const override
    {
        return "B";
    }

};

template<typename BASET>
class Factory
{
public:
    // could use a is_base type trait test here
    template <typename T, typename...ARGs>
    static BASET* create(ARGs&&...args)
    {
        return new T(forward<ARGs>(args)...);
    }

};
int main()
{
   Factory<C> factory;
   C* a = factory.create<A>(1);
   C* b = factory.create<B>(1.0f);
   cout << a->whoAmI() << endl;
   cout << b->whoAmI() << endl;
   return 0;
}
#包括
#包括
使用名称空间std;
C类
{
公众:
虚拟字符常量*whoAmI()常量=0;
};
A类:公共C类
{
公众:
A(int a1)
{

我是否认为完美地实现这一点是不可能的;函数的参数实际上是编译时的,与其他一些语言(如Java或C#)相比(它们可以通过反射动态调用函数)当然C++有编译时的反射,但是你想动态调用函数。我建议模仿这些运行时的反射:你可以使用一些东西,比如<代码>空隙*创建(const STD::vector and PARAMS);< /Cord>。你也可以提供宏或模板来帮助客户端创建这个“创建”。函数。如果通过引入一个
config
类来允许某种类型的动态初始化,我得到的结果会简单得多。该类基本上是一个
boost::any
列表,并且始终允许作为要创建的类的单个参数。
create()有什么问题
function?@Adrian你可以假设我的问题有很好的理由。用无用的答案对我来说毫无帮助是非常不礼貌的。我试着不去假设,但如果没有更多的信息,你可能正在尝试做一些不必要和/或适得其反的事情。说明你的理由s可能会帮助人们想出你没有想到的解决方案,因为你离问题太近了。作为一个拥有36k代表的人,你应该知道这一点。至于你说我粗鲁是因为你认为我在发垃圾邮件是粗鲁的。但是,如果你想得到更好的答案,那么就提出一个对整个社区更有用的问题。谢谢你用一个无用的答案对问题进行垃圾邮件处理。现在请删除它。好吧,最初的答案是无用的,因为它没有解决问题,部分地陈述了它。编辑的答案实际上似乎是有效的。你正在为每一组参数实例化Factory,所以Factory不再是一个真正的单例。但是我可以类似于元工厂的东西,它将引用所有不同的工厂,这些工厂将是一个单体(这对我来说很重要,因为一个无关的原因,我不想描述)。谢谢你,我道歉:)@shoosh,最初的答案是指你想去的方向。我不想为你做所有的工作
template<typename BaseT>
class Factory {
public:
    static Factory* instance() {
        static Factory inst;
        return &inst;
    }
    template<typename T>
    void reg(const string& name) {
        m_stock[name].reset(new Creator<T>);
    }
    BaseT* create(const string& name) {
        return m_stock[name]->create();
    }
private:
    struct ICreator {
        virtual BaseT* create() = 0;
    };
    template<typename T>
    struct Creator : public ICreator {
        virtual BaseT* create() {
            return new T;
        }
    };
    std::map<string, std::unique_ptr<ICreator>> m_stock;
};

template<typename BaseT, typename T>
class Register {
public:
    Register(const QString& name) {
        Factory<BaseT>::instance()->reg<T>(name);
    }
};
#include <iostream>
#include <utility>

using namespace std;

class C
{
public:
    virtual char const* whoAmI() const = 0;
};

class A : public C
{
public:
    A(int a1)
    {
        cout << "A(" << a1 << ")" << endl;
    }
    
    A(float a1)
    {
        cout << "A(" << a1 << ")" << endl;
    }
    
    virtual char const* whoAmI() const override
    {
        return "A";
    }
};

class B : public C
{
public:
    B(int a1)
    {
        cout << "B(" << a1 << ")" << endl;
    }
    
    B(float a1)
    {
        cout << "B(" << a1 << ")" << endl;
    }

    virtual char const* whoAmI() const override
    {
        return "B";
    }

};

template<typename BASET>
class Factory
{
public:
    // could use a is_base type trait test here
    template <typename T, typename...ARGs>
    static BASET* create(ARGs&&...args)
    {
        return new T(forward<ARGs>(args)...);
    }

};
int main()
{
   Factory<C> factory;
   C* a = factory.create<A>(1);
   C* b = factory.create<B>(1.0f);
   cout << a->whoAmI() << endl;
   cout << b->whoAmI() << endl;
   return 0;
}
#include <string>
#include <map>
#include <memory>
#include <utility>
#include <iostream>

using namespace std;

    template<typename BaseT, typename...ARGs>
    class Factory {
    public:
        static Factory* instance() {
            static Factory inst;
            return &inst;
        }
        template<typename T>
        void reg(const string& name) {
            m_stock[name].reset(new Creator<T>);
        }
        BaseT* create(const string& name, ARGs&&...args) {
            return m_stock[name]->create(forward<ARGs>(args)...);
        }
    private:
        struct ICreator
        {
            virtual BaseT* create(ARGs&&...) = 0;
            
        };
        template<typename T>
        struct Creator : public ICreator {
            virtual BaseT* create(ARGs&&...args) override
            {
                return new T(forward<ARGs>(args)...);
            }
        };
        std::map<string, std::unique_ptr<ICreator>> m_stock;
    };
    
    template<typename BaseT, typename T, typename...ARGs>
    class Register {
    public:
        Register(const string& name) {
            auto instance = Factory<BaseT, ARGs...>::instance();
            instance->template reg<T>(name);
        }
    };

struct C
{
    virtual char const * whoAmI() const = 0;
};

struct A : public C
{
    A(int a1, int a2)
    {
        cout << "Creating A(" << a1 << ", " << a2 << ")" << endl;
    }
    
    virtual char const * whoAmI() const override
    {
        return "A";
    }
};

struct B : public C
{
    B(int b1, int b2)
    {
        cout << "Creating B(" << b1 << ", " << b2 << ")" << endl;
    }
    B(int b1, int b2, int b3)
    {
        cout << "Creating B(" << b1 << ", " << b2  << ", " << b3 << ")" << endl;
    }
    virtual char const * whoAmI() const override
    {
        return "B";
    }
};

typedef int I;
Register<C, A, I, I> a("a");
Register<C, B, I, I> b("b");
Register<C, B, I, I, I> b3("b");
int main()
{
    C* a = Factory<C, I, I>::instance()->create("a", 1, 2);
    C* b = Factory<C, I, I>::instance()->create("b", 3, 4);
    C* b3 = Factory<C, I, I, I>::instance()->create("b", 5, 6, 7);
    cout << "I am a " << a->whoAmI() << endl;
    cout << "I am a " << b->whoAmI() << endl;
    cout << "I am a " << b3->whoAmI() << endl;
    return 0;
}
template <typename BaseT, typename...ARGs>
BaseT* create(const string& name, ARGs&&...args)
{
    return Factory<C, ARGs...>::instance()->create(name, forward<ARGs>(args)...);
}

int main()
{
    C* a = create<C>("a", 1, 2);
    C* b = create<C>("b", 3, 4);
    C* b3 = create<C>("b", 3, 4, 5);
    cout << "I am a " << a->whoAmI() << endl;
    cout << "I am a " << b->whoAmI() << endl;
    cout << "I am a " << b3->whoAmI() << endl;
    return 0;
}