在C ++中,如何创建包含可变模板对象的异构向量?

问题描述 投票:0回答:1

嗨,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); }

但是,我们可以添加更多:工厂的

Base

类。(如果您想知道为什么,这些将与其他类一起使用,而不是我的类P...。)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或类似的东西

我不太了解std::any,但是在rtfm-ing CppReference之后,它可以完成这项工作,接受的事实是,我需要将参数回退到派生类中需要的参数(并处理异常)。可悲的是,在实际项目中,compute()可以采用多个参数(我使用可变参数模板的原因...我不想关心每种compute方法中每种参数的数量或类型)派生的类),因此它将迫使我创建compute(const std::any&)compute(const std::any&, const std::any&)等。

((@ MaxLanghof:谢谢!)一种(丑陋的)解决方案是用手将所有可能的计算重载作为虚拟函数提供。

是的,您的权利,我也觉得很奇怪(我不会想出“丑陋”的程度,但是我还没有更漂亮的解决方案,所以...),但是它正在起作用。这里的缺点是,我将无法像开始时那样将类

P

(及相关类)存储在其自己的库中,以分离关注点(«MainProgram»和P
一起玩源自lib :: P)。
((@ MaxLanghof:谢谢!)在编译时完成整个_ps映射。

我还没有足够的C ++经验和知识来实现​​这样的目标。我需要解决这个问题,如果有人有特定的链接(我的意思是:不是Google上的第一个链接;))或示例,我将很高兴学习。

非常感谢您的回答!

嗨,StackOverflow社区!我正在使用可变参数模板,继承和抽象工厂模式进行工作,现在正努力使其协同工作。看来我已经达到...

c++ templates inheritance variadic-templates factory
1个回答
0
投票
您可以键入-擦除参数,只要您可以在呼叫站点指定它们即可。

至少:

© www.soinside.com 2019 - 2024. All rights reserved.