将动态仿函数传递给stl

APe*_*var 5 c++ inheritance stl functor

我对c ++比较陌生,这是我的第一篇文章,所以要温柔;-)

我理解如何传递函数指针或函数对象,就像许多stl函数需要的那样.我不清楚如何结合继承使用它.

具体来说,我想用几个从基础仿函数继承的仿函数调用一个stl函数.我没有找到关于这个主题的任何相关评论或最佳实践.这是一个简化的代码片段:

struct generator{
  virtual int operator()() = 0;
  virtual ~generator(){};
};

struct A : public generator{
  int operator()();
};

struct B : public generator{
  int operator()();
};

int main()
{
  auto v = std::vector<std::array<int, 500>>(2);
  std::array<std::shared_ptr<generator>, 2> functors = {{std::make_shared<A>(),
                                                         std::make_shared<B>()}};
  for (size_t i = 0; i < functors.size(); ++i)
    std::generate(std::begin(v[i]), std::end(v[i]),
                  *(functors[i]));
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译它给出:

clang++ -std=c++11 -g -Wall -Wextra test_stackoverflow.cpp 
test_stackoverflow.cpp:25:5: error: no matching function for call to 'generate'
    std::generate(std::begin(v[i]), std::end(v[i]),*(functors[i]));
    ^~~~~~~~~~~~~
/usr/lib/gcc/i686-linux-gnu/4.6/../../../../include/c++/4.6/bits/stl_algo.h:5003:5: note: candidate template ignored: substitution
      failure [with _ForwardIterator = int *, _Generator = generator]: parameter type 'generator' is an abstract class
    generate(_ForwardIterator __first, _ForwardIterator __last,
Run Code Online (Sandbox Code Playgroud)

是的*(functors [i])的类型是生成器.这将不允许动态访问A :: operator()和B :: operator().我理解如何(以rudmentally)解决这个问题.例如

std::generate(std::begin(v[i]), std::end(v[i], 
              [&]{ return functors[i]->operator()(); };
Run Code Online (Sandbox Code Playgroud)

然而,这似乎相当模糊,我正在寻找一种更清晰的方法来实现我的目标.

人们通常如何通过这种动态的仿函数.或者,如果这是不赞成的,最好的选择是什么?

我们非常欢迎任何帮助或建议.

eer*_*ika 1

您可能已经知道,问题在于std::generate按值获取生成器。要传递多态对象,必须通过引用传递。

在 c++11 中确实有一个针对此类问题的解决方案(除了 lambda 选项,我相信它仍然比我们在 c++11 之前的解决方案更优雅)。解决方案是std::ref。它返回一个可以按值传递的引用包装器。

这应该适合你:

std::generate(std::begin(v[i]), std::end(v[i]),
              std::ref(*(functors[i])));
Run Code Online (Sandbox Code Playgroud)

您可以将引用包装器作为函子传递的原因是它们实现了operator()