【问题标题】:how to pass member function pointer to std::function如何将成员函数指针传递给 std::function
【发布时间】:2014-02-11 20:23:41
【问题描述】:

如何通过函数将成员函数指针传递给std::function。我将通过比较来解释它(Live Test):

template<class R, class... FArgs, class... Args>
    void easy_bind(std::function<R(FArgs...)> f, Args&&... args){ 
}

int main() {
    fx::easy_bind(&Class::test_function, new Class);
    return 0;
}

我收到一条错误消息:

no matching function for call to ‘easy_bind(void (Class::*)(int, float, std::string), Class*)’

我只是不明白为什么函数指针在通过函数参数传递时不能传递给std::function。我怎样才能通过该功能?我愿意将easy_bind函数参数从std::function改成函数指针,但我真的不知道怎么做。

编辑:问题简化。

编辑:感谢@remyabel,我能够得到我需要的东西:http://ideone.com/FtkVBg

template <typename R, typename T, typename... FArgs, typename... Args>
auto easy_bind(R (T::*mf)(FArgs...), Args&&... args)
-> decltype(fx::easy_bind(std::function<R(T*,FArgs...)>(mf), args...)) {
    return fx::easy_bind(std::function<R(T*,FArgs...)>(mf), args...);
}

【问题讨论】:

  • 我正在研究一种解决方法,所以我的答案目前不完整。 Generic functor for functions with any argument list 似乎是一个不错的候选者,但这并没有考虑到成员函数指针。
  • 您希望RFArgsArgs 有哪些类型?
  • 我得到了这个easy_bind 使用全局函数:ideone.com/FtkVBg。但是成员函数仍然无法工作:(
  • @BenVoigt R(FArgs...) 是一个函数,在我的例子中是&amp;Class::test_function 的类型; Argsnew Class 的类型
  • @Gasim 我编辑了我的答案,但是我很努力,无法弄清楚如何消除将无用对象传递给函数调用的需要。也许有人可以看看。编辑:从头开始,它按预期工作。

标签: c++ c++11 parameter-passing function-pointers


【解决方案1】:

http://en.cppreference.com/w/cpp/utility/functional/mem_fn 是你应该使用的

struct Mem
{
    void MemFn() {}
};

std::function<void(Mem*)> m = std::mem_fn(&Mem::MemFn);

【讨论】:

  • 相比m = &amp;Mem::MemFn有什么优势
  • 它编译!因为 std::mem_fn 将构造一个函数对象,该函数对象在调用时将 Mem* 作为其第一个参数,而 &Mem::MemFn 将返回一个 void (__thiscall Mem::* const &)(void)
  • 好吧,您仍然可以使用您的答案来完成一些模板魔术,就像 op 最后所做的那样,所以我不会说它毫无意义。
  • @ACB 是的,auto func3 = fx::easy_bind(std::mem_fn(&amp;SomeStruct::function), new SomeStruct); 无法编译。如果您弄清楚如何让它发挥作用,您的答案可能会得到改进(并且可能会被接受而不是我的)。我以为我只是在重新发明mem_fn,但我想它们并不相同。
  • @ACB ideone.com/lYd5DQ 他们似乎都为我编译......我从来没有真正理解 mem_fn 的意义。我认为 std::function 在传递时会在 mem_fn 周围包装一个成员函数指针,但这只是一个想法
【解决方案2】:

我认为问题可以归结为:

template<class R, class... FArgs>
void test(std::function<R(FArgs...)> f)
{
}

int main() {
  test(&SomeStruct::function);
}

没有easy_bind 的其余部分,错误消息非常相似:

main.cpp: In function 'int main()':
main.cpp:63:31: error: no matching function for call to 
'test(void (SomeStruct::*)(int, float, std::string))'
     test(&SomeStruct::function);
main.cpp:63:31: note: candidate is:
main.cpp:49:10: note: template<class R, class ... FArgs> 
void test(std::function<_Res(_ArgTypes ...)>)
     void test(std::function<R(FArgs...)> f)
          ^
main.cpp:49:10: note:   template argument deduction/substitution failed:
main.cpp:63:31: note:   'void (SomeStruct::*)(int, float, std::string) 
{aka void (SomeStruct::*)(int, float, std::basic_string<char>)}' 
is not derived from 'std::function<_Res(_ArgTypes ...)>'
     test(&SomeStruct::function);

本质上,它不能神奇地为您创建std::function。你需要类似Functor 别名的东西。


感谢generic member function pointer as a template parameter 中提供的答案,您可以这样做:

//Test Case:
struct SomeStruct {
public:
 int function(int x, float y, std::string str) {
   std::cout << x << " " << y << " " << str << std::endl;
   return 42;
 }
};

template <typename Ret, typename Struct, typename ...Args>
std::function<Ret (Struct*,Args...)> proxycall(Ret (Struct::*mf)(Args...))
{
    return std::function<Ret (Struct*,Args...)>(mf);
}

int main() {
    auto func3 = fx::easy_bind(proxycall(&SomeStruct::function), new SomeStruct);
    int ret = func3(5, 2.5, "Test3");
    std::cout << ret << "\n";

    return 0;
}

现在它会自动运行。

Live Example

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-29
    • 2020-04-28
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多