【问题标题】:Am I reinventing the wheel with this trivial method call forwarding class?我是在用这个简单的方法调用转发类重新发明轮子吗?
【发布时间】:2012-05-15 23:41:47
【问题描述】:

我刚刚发现自己正在创建一个类

template <typename T> struct invoker {
  void operator()(T& it) const {it();}
};

所以我可以将invoker&lt;foo&gt; 传递给想要用不同的foo 实例反复调用invoker&lt;foo&gt;::operator()(foo&amp;) 的东西(它不在我的控制之下),让它将这些调用转发给@987654325 @ 的foo::operator()() 方法。

我知道它只有几行,但这似乎是 STL 的函数或 boost::bind 可能已经提供的那种东西。除了我看不到诀窍,如果有的话。 (我敢肯定我不是第一个使用这种东西的人;它有名字吗?)

【问题讨论】:

  • 我认为 c++11 也有这个功能
  • 现在我在 g++ 4.4.5;我认为 g++ 直到 4.5 才有 lambdas。如果发布了一个 lambda 解决方案,我很想知道;在 g++ 版本升级之前,我可以使用我的调用程序类。
  • 你为什么不直接打电话给foo::operator()?我的意思是,调用invoker::operator() 的类必须执行类似some_invoker(some_foo); 的操作,而您可以这样称呼它:some_foo();。您正在添加不必要的间接层。
  • 我不知道为什么你会使用这个类而不是简单地使用 T 作为函数类型。
  • @DeadMG: (和其他人)不,这不起作用:我正在处理的事情的 API(TBB 的 parallel_for_each,具体来说)只让我传入一个调用者,然后在以 foos 作为连续参数的循环中调用它。这也是为什么我注意到更改代码不是一种选择的原因。我当然可以想象改变它/创建一个变体来消除对调用者的需要。

标签: c++ templates stl functor boost-bind


【解决方案1】:

好吧,您可以使用std::bind,也可能使用boost::bind 来实现相同的行为:

#include <string>
#include <iostream>
#include <functional>

struct foo {
    void operator()() {
        std::cout << "Hallo, im at addr: " << std::hex << this << std::endl;
    }
};

int main() {
    std::function<void(foo*)> fun = std::bind(&foo::operator(), std::placeholders::_1);
    foo f1, f2;
    fun(&f1);
    fun(&f2);
}

输出:

Hallo, im at addr: 0xbffc396a
Hallo, im at addr: 0xbffc3969

如果您为参数类型使用模板类,则无需重新发明轮子即可拥有相同的行为。

编辑:正如 Crazy Eddie 指出的那样,您可以使用 boost::mem_fnstd::mem_fn

std::function<void(foo*)> fun = std::mem_fn(&foo::operator());

而不是bind

【讨论】:

  • 您实际上不需要在这里绑定,省略它是值得的。 Bind 必须通过参数转换系统来合并两个参数列表并调用目标可调用对象。 boost::mem_fn 会做到这一点,实际上 bind() 成员指针使用它。
  • @CrazyEddie 不错,前段时间我用过mem_fn,但完全忘记了。编辑了我的答案:D
  • 好的,这正是我正在寻找的东西,谢谢;很明显,当您看到它时,我不知何故说服自己(在这里为时已晚),因为我感兴趣的 foo 方法没有参数,所以 _1 占位符没有角色......所以错了。
  • 我指的是增强型,但标准型也可以……只是几乎没有那么好。
【解决方案2】:

是的,您正在重新发明轮子。 std::mem_fun_ref 做你想做的事。

std::vector<foo> foos;

...

std::for_each(foos.begin(), foos.end(), std::mem_fun_ref(&foo::operator()));

或者:

std::vector<foo*> foos;

...

std::for_each(foos.begin(), foos.end(), std::mem_fun(&foo::operator()));

不必纠结参数是否为 ptr 是 boost::mem_fn 的一大好处。

任何比这更复杂的东西,你开始在 C++03 绑定器上遇到麻烦,需要像 boost.bind 这样更有表现力的东西。

【讨论】:

  • 只是想指出 std::mem_funstd::mem_fun_ref 在 C++11 中已被 std::mem_fn 弃用。
猜你喜欢
  • 2011-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-01
  • 2016-10-03
  • 2012-04-07
  • 2013-05-03
  • 1970-01-01
相关资源
最近更新 更多