【问题标题】:Passing dynamic functor to stl将动态函子传递给 stl
【发布时间】:2015-02-06 00:21:12
【问题描述】:

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

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

具体来说,我想调用一个 stl 函数,其中包含几个从基本函子继承的函子。我没有找到关于这个主题的任何相关评论或最佳实践。这里是一个简化的代码sn -p:

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;
}

编译得到:

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,

是的,*(functors[i]) 的类型是生成器。这将不允许动态访问 A::operator() 和 B::operator()。我了解如何(粗略地)解决这个问题。例如

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

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

通常如何传递这样的动态函子。或者如果不赞成这样做,最好的选择是什么?

欢迎任何帮助或建议。

【问题讨论】:

    标签: c++ inheritance stl functor


    【解决方案1】:

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

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

    这应该适合你:

    std::generate(std::begin(v[i]), std::end(v[i]),
                  std::ref(*(functors[i])));
    

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

    【讨论】:

    • 另外,std::function
    • 已确认,可以将std::ref 传递给算法。不知道。 coliru.stacked-crooked.com/a/db815184c44240ad
    • 老实说。我从未听说过 std::ref。非常感谢你的帮忙。您是否认为 lambda 比它更受欢迎,如果是,为什么?
    • @APevar 如果您需要捕获函子之外的其他内容,则 lambda 非常棒,但既然您不需要,我认为 std::ref 非常适合该问题。
    • 我查看了有关 std::ref 的语义。我(想我)明白这偶尔会有用。这在生产代码中实际使用的频率如何? std::ref 是否比 lambda 捕获更实际相关,如果是,什么时候会出现这种情况?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-12
    • 2020-09-28
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    相关资源
    最近更新 更多