嗨,StackOverflow社区!
我当时正在使用可变参数模板,继承和抽象工厂模式,现在正在努力使其协同工作。看来我对这些主题的了解程度是目前为止最遥远的,因此,如果您能给我一个提示或代码示例,您将不胜感激!在此先感谢;)
这里是上下文(我很抱歉!有几行代码...):]]
我有一个[[Base
类template<typename... Params>
class P
{
public:
virtual void compute(Params&... ps) = 0;
// other things ...
};
和类Derived
template<typename... Params>
class AP : public P<Params...>
{
public:
void compute(Params&... ps) override { _compute(std::forward<Params&>(ps)...); }
private:
void _compute(std::string& str) {std::cout << "AP::compute str " << str << std::endl;}
};
using A = AP<std::string>;
template<typename... Params>
class BP : public P<Params...>
{
public:
void compute(Params&... ps) override { _compute(std::forward<Params&>(ps)...); }
private:
void _compute(int& i) {std::cout << "BP::compute i " << i << std::endl;}
};
using B = BP<int>;
到这里,没有问题!如果我制作一个小main()
,则可以正常使用:
int main()
{
std::unique_ptr<P<int>> p1 = std::make_unique<B>();
int i = 15;
p1->compute(i);
std::unique_ptr<P<std::string>> p2 = std::make_unique<A>();
std::string str = "abc";
p2->compute(str);
}
但是,我们可以添加更多:工厂的类。(如果您想知道为什么,这些将与其他类一起使用,而不是我的类P...。)Base
template<typename Base>
class Creator
{
public:
virtual std::unique_ptr<Base> create() = 0;
};
template<class Key, class T>
class Factory
{
public:
void store(Key key, std::unique_ptr<Creator<T>>&& creator)
{
_crs[key] = std::move(creator);
}
std::unique_ptr<T> create(Key key)
{
return _crs[key]->create();
}
private:
std::map<Key, std::unique_ptr<Creator<T>>> _crs;
};
及其能够构建相关对象的实现:P
template<typename Derived, typename... Params>
class PCreator : public Creator<P<Params...>>
{
public:
std::unique_ptr<P<Params...>> create() override
{
return std::make_unique<Derived>();
}
};
template<typename... Params>
class PFactory : public Factory<std::string, P<Params...>>
{
public:
PFactory()
{
this->store("int", std::make_unique<PCreator<BP<int>>>);
this->store("string", std::make_unique<PCreator<AP<std::string>>>);
}
// create() and store() methods inherited
};
如果我实例化,则编译器显然无法完成其工作,因为它希望PFactory的模板参数将其转发给PFactory
Factory<std::string, P<Params...>>
。但是,我的工厂只能创建P
对象的一个“类型”,一个可以使用这些Params
的对象。这就是我一个人走的路(可悲的是,我的任何一个同事都没有能力帮助我...)我的目标是能够写这样的东西:class Thing
{
const std::array<std::string, 2> a = {"one", "two"};
public:
Thing()
{
PFactory f;
for(const auto& e : a)
_ps[e] = std::move(f.create(e));
}
void compute()
{
int i = 100;
std::string str = "qwerty";
// additional computations...
_ps["one"]->compute(i);
// additional computations...
_ps["two"]->compute(str);
}
private:
std::map<std::string, std::unique_ptr<P>> _ps;
};
这是我尝试在CompilerExplorer上进行工作和返工的PoC,上面的来源来自哪里。
任何帮助将不胜感激!
[[Edit]
是的,我以为我可以欺骗编译器以创建带有运行时信息的各种方法签名。解决方案总结:((@ walnut:谢谢!)让计算取std :: any或类似的东西一起玩源自lib :: P)。我不太了解
std::any
,但是在rtfm-ing CppReference之后,它可以完成这项工作,接受的事实是,我需要将参数回退到派生类中需要的参数(并处理异常)。可悲的是,在实际项目中,compute()
可以采用多个参数(我使用可变参数模板的原因...我不想关心每种compute
方法中每种参数的数量或类型)派生的类),因此它将迫使我创建compute(const std::any&)
和compute(const std::any&, const std::any&)
等。((@ MaxLanghof:谢谢!)一种(丑陋的)解决方案是用手将所有可能的计算重载作为虚拟函数提供。是的,您的权利,我也觉得很奇怪(我不会想出“丑陋”的程度,但是我还没有更漂亮的解决方案,所以...),但是它正在起作用。这里的缺点是,我将无法像开始时那样将类
P
(及相关类)存储在其自己的库中,以分离关注点(«MainProgram»和P
((@ MaxLanghof:谢谢!)在编译时完成整个_ps映射。
我还没有足够的C ++经验和知识来实现这样的目标。我需要解决这个问题,如果有人有特定的链接(我的意思是:不是Google上的第一个链接;))或示例,我将很高兴学习。
非常感谢您的回答!
嗨,StackOverflow社区!我正在使用可变参数模板,继承和抽象工厂模式进行工作,现在正努力使其协同工作。看来我已经达到...
至少: