如何指示容器中的多态仿函数完成其工作和 return 结果?

How to instruct a polymorphic functor in a container to do its job and return results?

我有一个 std::vector<> 指向基函子的指针。这个容器,一个计算器class,应该能够保存任意数量的计算任意统计数据的函数对象。

我正在努力解决的部分是如何为容器编写一个方法 class,迭代这些指针,从 hte 组中选择您感兴趣的那个,告诉它做它的工作是调用 operator(),然后 returns 结果。

这里有一些代码可以说明这个想法:

#include <iostream>
#include <memory> //shared_ptr
#include <vector>

class BaseFunctor{
    virtual double operator()(std::vector<double> inputs) = 0;  
};

class Sum : public BaseFunctor{
    double operator() (std::vector<double> inputs){ 
        double sum (0.0);
        for(auto elem : inputs)
            sum += elem;
        return sum;
    }
};

class Prod : public BaseFunctor{
    double operator() (std::vector<double> inputs){ 
        double sum (1.0);
        for(auto elem : inputs)
            sum *= elem;
        return sum;
    }
};

class Calculator {
private:
    std::vector<std::shared_ptr<BaseFunctor>> m_stats;
    std::vector<double> m_simple_data;
public:
    Calculator() 
        : m_simple_data({1.0, 2.0, 3.0}) {};
    void addStat(std::shared_ptr<BaseFunctor> stat) { 
        m_stats.push_back(stat); 
    }
    // calculate stat?
};

int main() {

    Calculator calc;
    calc.addStat(std::make_shared<Sum>());
    calc.addStat(std::make_shared<Prod>());
    
    return 0;
}

现在,我如何告诉 calc 给我产品,而且只给我产品?尤其是当我无法控制用户最终对哪些统计数据感兴趣时?

我想我可以将指针存储在 map 中,但这似乎是多余的:使密钥与 class.

同名

Here 是一个想法,但无法编译。

这可行,但我愿意 comments/criticisms/suggestions。

#include <iostream>
#include <memory> //unique_ptr
#include <map>
#include <vector>
#include <string>
#include <functional>

class BaseFunctor{
public:
    virtual double operator()(std::vector<double> inputs) = 0;  
    virtual std::string name() = 0;  
};

class Sum : public BaseFunctor{
    double operator() (std::vector<double> inputs){ 
        double sum (0.0);
        for(auto elem : inputs)
            sum += elem;
        return sum;
    }
    std::string name() { return "sum"; }
};

class Prod : public BaseFunctor{
    double operator() (std::vector<double> inputs){ 
        double prod (1.0);
        for(auto elem : inputs)
            prod *= elem;
        return prod;
    }
    std::string name() { return "prod"; }
};

class Calculator {
private:
    std::map<std::string, std::unique_ptr<BaseFunctor> > m_stats;
    std::vector<double> m_simple_data;
public:
    Calculator() 
        : m_simple_data({1.0, 2.0, 5.0}) {};
        
    void addStat(std::unique_ptr<BaseFunctor> stat) { 
        m_stats.insert(
            std::pair<std::string, std::unique_ptr<BaseFunctor>>(
                stat->name(),
                std::move(stat)
            )   
        );
        //m_stats.push_back(std::move(stat)); 
    }
    
    double calc(std::string op_name){
        return (*m_stats[op_name])(m_simple_data);
    }
};

int main() {

    Calculator thing;
    thing.addStat(std::unique_ptr<BaseFunctor>(new Sum()) );
    thing.addStat(std::unique_ptr<BaseFunctor>(new Prod()) );

    std::cout << "sum: " << thing.calc("sum") << "\n";
    std::cout << "prod: " << thing.calc("prod");
    
    return 0;
}