STL for_each具有多个返回值和/或虚拟基类仿函数

Noa*_*oah 2 c++ virtual stl functor

我试图在我的代码中转换一些循环来使用STL的for_each功能.目前,我在同一组数据上计算和累加两个单独的值,要求我循环数据两次.为了速度,我想循环一次并积累两个值.建议使用for_each,因为它显然可以很容易地用于多线程或多处理器实现(我还没有学会如何做到这一点.)

创建一个只循环数据并计算两个值的函数很容易,但我需要返回两者.要与for_each一起使用,我需要在每次迭代时返回两个计算值,以便STL可以对它们求和.根据我的理解,这是不可能的,因为for_each期望返回一个值.

除了更清晰的代码(可以说是?)之外,使用for_each的目标是最终转移到多线程或多处理器实现,以便可以并行完成数据循环,从而使事情运行得更快.

有人建议我使用仿函数而不是函数.但是,这引发了两个问题.

  1. 如何使用仿函数代替两个值的返回累积?
  2. 我有两种应用此算法的方法.当前代码有一个虚拟基类,然后是两个继承和实现实际工作代码的类.我无法弄清楚如何使用"虚拟函子",以便每个方法类都可以实现自己的版本.

谢谢!

Oli*_*rth 6

以下是使用仿函数并行执行两个累加的示例.

struct MyFunctor
{
    // Initialise accumulators to zero
    MyFunctor() : acc_A(0), acc_B(0) {}

    // for_each calls operator() for each container element
    void operator() (const T &x)
    {
        acc_A += x.foo();
        acc_B += x.bar();
    }

    int acc_A;
    int acc_B;
};


// Invoke for_each, and capture the result
MyFunctor func = std::for_each(container.begin(), container.end(), MyFunctor());
Run Code Online (Sandbox Code Playgroud)

[请注意,您也可以考虑使用std::accumulate()适当的重载operator+.]

至于虚拟仿函数,你不能直接做这些,因为STL函数按值而不是通过引用来获取仿函数(因此你会遇到切片问题).您需要实现一种"代理"仿函数,该仿函数又包含对虚拟仿函数的引用.* 遵循:

struct AbstractFunctor
{
    virtual void operator() (const T &x) = 0;
};

struct MyFunctor : AbstractFunctor
{
    virtual void operator() (const T &x) { ... }
};

struct Proxy
{
    Proxy(AbstractFunctor &f) : f(f) {}
    void operator() (const T &x) { f(x); }
    AbstractFunctor &f;
};

MyFunctor func;
std::for_each(container.begin(), container.end(), Proxy(func));
Run Code Online (Sandbox Code Playgroud)

*Scott Meyers在他出色的Effective STL的第38项中给出了这种技术的一个很好的例子.