【问题标题】:couldn't deduce template parameter of return type无法推断返回类型的模板参数
【发布时间】:2018-07-22 09:32:39
【问题描述】:

我正在尝试使用 std::function 创建一个抽象工厂

普通工厂工作正常,但是当我想返回工厂(另一个 std::function)而不是对象时,我收到以下错误:

/home/nikolai/Projects/cpplearn/AbstractFactoryPattern/Main.cpp:9:45: error: no matching function for call to ‘factoryProducer(const char [6])’
  auto shapeFactory = factoryProducer("shape")();
                                             ^
In file included from /home/nikolai/Projects/cpplearn/AbstractFactoryPattern/Main.cpp:3:
/home/nikolai/Projects/cpplearn/AbstractFactoryPattern/AbstractFactory.hpp:48:1: note: candidate: ‘template<class ReturnType> ReturnType abstractfactory::factoryProducer(const string&)’
 factoryProducer(const std::string& tag = {})
 ^~~~~~~~~~~~~~~
/home/nikolai/Projects/cpplearn/AbstractFactoryPattern/AbstractFactory.hpp:48:1: note:   template argument deduction/substitution failed:
/home/nikolai/Projects/cpplearn/AbstractFactoryPattern/Main.cpp:9:45: note:   couldn't deduce template parameter ‘ReturnType’
  auto shapeFactory = factoryProducer("shape")();

我将工厂定义如下:

namespace factory 
{

/**
 * A template for a factory, which is just a std::function.
 * See AnimalFactory.hpp for example usage.
 */
template <class ReturnType, class ...Args>
using Factory = std::function<ReturnType(Args...)>;

}

工厂生产者工作正常,除了最后一个,我试图创建一个工厂工厂,返回类型必须是动态的:

namespace abstractfactory 
{

using ShapeFactory = factory::Factory<std::unique_ptr<Shape>>;
using ColorFactory = factory::Factory<std::unique_ptr<Color>>;

ShapeFactory shapeFactoryProducer(const std::string& tag = {})
{
    return [=]
    {
        if(tag == "rectangle")
            return std::unique_ptr<Shape>(new Rectangle());
        else if(tag == "circle")
            return std::unique_ptr<Shape>(new Circle());
        else if(tag == "square")
            return std::unique_ptr<Shape>(new Square());
        else
            return std::unique_ptr<Shape>(nullptr);
    };
}

ColorFactory colorFactoryProducer(const std::string& tag = {})
{
    return [=]
    {
        if(tag == "green")
            return std::unique_ptr<Color>(new Green());
        else if(tag == "blue")
            return std::unique_ptr<Color>(new Blue());
        else if(tag == "red")
            return std::unique_ptr<Color>(new Red());
        else
            return std::unique_ptr<Color>(nullptr);
    };
}

template <class ReturnType>
ReturnType
factoryProducer(const std::string& tag = {})
{
    return [=]
    {
        if(tag == "shape")
            return shapeFactoryProducer;
        else if(tag == "color")
            return colorFactoryProducer;
        else
            return [=] {};
    };
}

}

如何实现函数factoryProducer的动态返回类型?

编辑:新代码(仍然不起作用):

struct FactoryType {};
struct ShapeType {};
struct ColorType {};

template <class TFactory, class ReturnType>
ReturnType factoryProducer(TFactory tag)
{
    return [=]
    {
        if constexpr (std::is_same<TFactory, ShapeType>::value)
            return shapeFactoryProducer;
        else if constexpr (std::is_same<TFactory, ColorType>::value)
            return colorFactoryProducer;
    };
}

auto shapeFactoryProducer = factoryProducer(ShapeType());

【问题讨论】:

  • 在 C++ 中无法实现“动态返回类型”
  • tag 必须是字符串吗?如果您可以使用枚举代替,则可以将其设为模板参数。
  • @J.Daniel - 你明白了:你不能将constexpr 作为一个简单的函数参数传递(运行时已知)。你必须通过一些已知的编译时间;通常是某种类型的模板值。正如 Henry Menke 所建议的,std::string 是一个复杂的问题,如果可以的话,最好是一个枚举或可以用作模板参数的东西(整数值?标签类型?)。
  • @J.Daniel - 不是那样,而是(1)在 lambda 中使用 if constexpr(从 C++17 开始可用)或(2)开发不同的 factoryProducer(和不同的 lambda)对于不同的标签,是的......应该是可能的。
  • 如果你在编译时就知道你想要一个形状工厂,为什么不直接打电话给shapeFactoryProducer

标签: c++ templates factory


【解决方案1】:

您的返回类型推导语法离题了。这是正确的(需要 C++17)。

template <class TFactory>
auto factoryProducer(TFactory tag)
{   
    if constexpr (std::is_same<TFactory, ShapeType>::value)
        return shapeFactoryProducer;
    else if constexpr (std::is_same<TFactory, ColorType>::value)
        return colorFactoryProducer;
}   

【讨论】:

  • 谢谢,这确实是我想要的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多