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!您的示例让我了解了很多事情到目前为止。我用你的工作来改进我的工作,这导致了我的文章的第二次编辑(很遗憾)。再次感谢你的帮助!