简体   繁体   English

使用unique_ptr的工厂模式

[英]Factory pattern with unique_ptr

I have abstract class Agent, and few derived: Predator, Prey etc. I would like to make a factory, that gives me unique_ptr which I can store in vector of base class. 我有抽象类Agent,很少有派生类:Predator,Prey等。我想建立一个工厂,这给了我unique_ptr,我可以将其存储在基类的向量中。

Problem is, when I have: 问题是,当我有:

using creatorFunctionType = std::unique_ptr<Agent>(*)();

this part is ok, but in map I cannot use lambda with: 这部分还可以,但是在地图中,我不能将lambda用于:

return std::make_unique<Predator>();

But when I am trying to use template: 但是当我尝试使用模板时:

template <class T>
using creatorFunctionType = std::unique_ptr<T>(*)();

The rest of functions doesn't compile. 其余功能无法编译。 I am nearby sure, I missed something important about templates, but no idea what. 我肯定在附近,我错过了一些有关模板的重要知识,但不知道该怎么做。 Can you give me some hints? 你能给我一些提示吗?

Posting full code, may be helpful 发布完整代码,可能会有所帮助

AgentFactory.h AgentFactory.h

#include "Interfaces/Agent.h"
#include "Enums.h"
#include <map>
#include <memory>

class AgentFactory
{
public:
    template <class T>
    using creatorFunctionType = std::unique_ptr<T>(*)();

    AgentFactory();
    std::unique_ptr<Agent> createAgent(Enums::AgentType agentType);
private:
    void registerAgentType(Enums::AgentType agentType, creatorFunctionType 
    creatorFunction);

    std::map<Enums::AgentType, creatorFunctionType> factoryRegister;
};

AgentFactory.cpp AgentFactory.cpp

#include "AgentFactory.h"
#include "Predator.h"
#include "Prey.h"

AgentFactory::AgentFactory()
{
    registerAgentType(Enums::AgentType::Predator, []() { return         
    std::make_unique<Predator>(); });
    registerAgentType(Enums::AgentType::Prey, []() { return     
    std::make_unique<Prey>(); });
}

std::unique_ptr<Agent> AgentFactory::createAgent(Enums::AgentType 
agentType)
{
    if (auto it = factoryRegister.find(agentType); it != 
    factoryRegister.end()) {
        return it->second();
    }

    return nullptr;
}

void AgentFactory::registerAgentType(Enums::AgentType agentType, 
creatorFunctionType creatorFunction)
{
    factoryRegister.insert(std::pair<Enums::AgentType, 
    creatorFunctionType>(agentType, creatorFunction));
}

Compilation errors: 编译错误:

1>d:\predator-prey\predator-prey\agentfactory.h(15): error C2955: 'AgentFactory::creatorFunctionType': use of alias template requires template argument list
1>d:\predator-prey\predator-prey\agentfactory.h(10): note: see declaration of 'AgentFactory::creatorFunctionType'
1>d:\predator-prey\predator-prey\agentfactory.h(17): error C3203: 'creatorFunctionType': unspecialized alias template can't be used as a template argument for template parameter '_Ty', expected a real type
1>d:\predator-prey\predator-prey\agentfactory.cpp(14): error C2064: term does not evaluate to a function taking 0 arguments
1>d:\predator-prey\predator-prey\agentfactory.cpp(22): error C3203: 'creatorFunctionType': unspecialized alias template can't be used as a template argument for template parameter '_Ty2', expected a real type
1>d:\predator-prey\predator-prey\agentfactory.cpp(22): fatal error C1903: unable to recover from previous error(s); stopping compilation

When creatorFunctionType is defined as creatorFunctionType定义为

using creatorFunctionType = std::unique_ptr<Agent>(*)();

creatorFunctionType is a pointer-to-function that expects functions which return a std::unique_ptr<Agent> . creatorFunctionType是指向函数的指针,该函数需要返回std::unique_ptr<Agent>函数。

However, your lambdas do not have explicit return types, so the compiler deduces their return types as std::unique_ptr<Predator> and std::unique_ptr<Prey> , respectively, based on their return statements. 但是,您的lambda没有显式的返回类型,因此编译器根据它们的return语句分别将其返回类型推导为std::unique_ptr<Predator>std::unique_ptr<Prey>

A non-capturing lambda is implicitly convertible to a pointer-to-function, which is what you want in this case, however your lambdas do not return std::unique_ptr<Agent> , so they cannot be assigned to creatorFunctionType . 非捕获的lambda可隐式转换为函数指针,在这种情况下,这就是您想要的,但是lambda不会返回std::unique_ptr<Agent> ,因此无法将它们分配给creatorFunctionType The types simply do not match. 类型根本不匹配。

You need to be explicit about the return type of your lambdas so they match the correct signature that creatorFunctionType is expecting, eg: 您需要明确关于lambda的返回类型,以便它们与creatorFunctionType期望的正确签名匹配,例如:

AgentFactory::AgentFactory()
{
    registerAgentType(Enums::AgentType::Predator,
        []() -> std::unique_ptr<Agent> { return std::make_unique<Predator>(); }
    );
    registerAgentType(Enums::AgentType::Prey,
        []() -> std::unique_ptr<Agent> { return std::make_unique<Prey>(); }
    );
}

With the above code, the lambdas will now return std::unique_ptr<Agent> , satisfying what creatorFunctionType expects. 使用上面的代码,lambdas现在将返回std::unique_ptr<Agent> ,满足creatorFunctionType期望。 And the return statements still work as-is because std::unique_ptr<T> can be initialized with a std::unique_ptr<U> as long as U derives from T , which is true in your case since Predator and Prey derive from Agent . 并且return语句仍然按原样工作,因为只要U源自T ,就可以使用std::unique_ptr<U>初始化std::unique_ptr<T> ,这在您的情况下是正确的,因为PredatorPrey源自Agent

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM