C++ 在C++;,如何创建包含可变模板对象的异构向量?
嗨,我的社区 我在工作中使用可变模板、继承和抽象工厂模式,现在正努力使其协同工作。看来我已经达到了我目前所知道的关于这些主题的最远的程度,所以如果你能给我一个提示或一个代码示例,你会得到我全部的感谢!提前感谢;) 以下是上下文(抱歉!这里有几行代码…): 我有一个基础班C++ 在C++;,如何创建包含可变模板对象的异构向量?,c++,templates,inheritance,variadic-templates,factory,C++,Templates,Inheritance,Variadic Templates,Factory,嗨,我的社区 我在工作中使用可变模板、继承和抽象工厂模式,现在正努力使其协同工作。看来我已经达到了我目前所知道的关于这些主题的最远的程度,所以如果你能给我一个提示或一个代码示例,你会得到我全部的感谢!提前感谢;) 以下是上下文(抱歉!这里有几行代码…): 我有一个基础班 模板 P类 { 公众: 虚空计算(参数和…ps)=0; //其他事情。。。 }; 和派生类 模板 AP类:公共P { 公众: void compute(Params&…ps)重写{u compute(std::forward(
模板
P类
{
公众:
虚空计算(参数和…ps)=0;
//其他事情。。。
};
和派生类
模板
AP类:公共P
{
公众:
void compute(Params&…ps)重写{u compute(std::forward(ps)…);}
私人:
void_compute(std::string&str){std::cout您可以键入擦除参数,只要您可以在调用站点指定它们
最低限度:
#include <functional>
#include <any>
#include <map>
#include <iostream>
template<typename Ret>
struct AnyCallable
{
AnyCallable() {}
template<typename F>
AnyCallable(F&& fun) : AnyCallable(std::function(fun)) {}
template<typename ... Args>
AnyCallable(std::function<Ret(Args...)> fun) : m_any(fun) {}
template<typename ... Args>
Ret operator()(Args&& ... args)
{
return std::invoke(std::any_cast<std::function<Ret(Args...)>>(m_any), std::forward<Args>(args)...);
}
template<typename ... Args>
Ret compute(Args ... args)
{
return operator()(std::forward<Args>(args)...);
}
std::any m_any;
};
template<>
struct AnyCallable<void>
{
AnyCallable() {}
template<typename F>
AnyCallable(F&& fun) : AnyCallable(std::function(fun)) {}
template<typename ... Args>
AnyCallable(std::function<void(Args...)> fun) : m_any(fun) {}
template<typename ... Args>
void operator()(Args&& ... args)
{
std::invoke(std::any_cast<std::function<void(Args...)>>(m_any), std::forward<Args>(args)...);
}
template<typename ... Args>
void compute(Args ... args)
{
operator()(std::forward<Args>(args)...);
}
std::any m_any;
};
using P = AnyCallable<void>;
void A(std::string& str) {std::cout << "AP::compute i " << str << std::endl;}
void B(int i) {std::cout << "BP::compute i " << i << std::endl;}
class Thing
{
public:
Thing(){}
void compute()
{
int i = 100;
std::string str = "qwerty";
// additional computations...
ps["one"].compute<int>(i);
// additional computations...
ps["two"].compute<std::string&>(str);
}
private:
std::map<std::string, P> ps = { { "one", B }, { "two", A } };
};
#包括
#包括我不确定这一切的意义是什么,但从根本上说:\u ps[“一”]
和\u ps[“两”]
具有相同的静态类型。因此,compute
必须是一个接受不同类型的模板,在这种情况下,它不能是virtual
,或者必须重载它在基类中接受的不同类型。当前,compute
在基类中是一个单独的非重载函数。这无法工作k、 我所看到的使其以这种方式工作的唯一方法是让compute
接受std::any
或类似的东西,但是调用者仍然必须知道\u ps
apriori中对象的派生类型,以便不提供错误的参数类型,在这种情况下,使用带有基类指针的容器是没有意义的。编译器需要在编译时知道(*_ps[“…”)
的类型。由于该类型是在编译时确定的,因此它不能依赖于运行时值。您希望该类型具有compute(i)
和compute(str)
方法。但您不能具有虚拟的
和模板化的成员函数。一个(丑陋)解决方案是手动提供所有可能的compute
重载作为虚拟函数。您希望\u ps[“one”]->compute(str);
?另一个可能的解决方案是在编译时执行整个\u ps
映射。但是,您不能(轻松地)使用运行时字符串值来代替例如“one”
。通常,类型擦除要求a)整个接口是(非模板化)的一部分基类,或b)调用方/用户代码知道他们需要检索什么类型。您目前都不满足这两个条件,如果您想要一个异构容器,您必须选择其中一个选项。模板类AP
没有真正起作用,只有AP
可以起作用。非常感谢@Caleth!您的示例让我了解了很多事情到目前为止。我用你的工作来改进我的工作,这导致了我的文章的第二次编辑(很遗憾)。再次感谢你的帮助!