C++ 使用 std::bind 时从 std::function 获取函数指针
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10938774/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get function pointer from std::function when using std::bind
提问by chris
I'm trying to use std::function
in conjunction with std::bind
, but I'm having some problems.
我正在尝试与std::function
结合使用std::bind
,但我遇到了一些问题。
This works:
这有效:
#include <functional>
#include <iostream>
void print() {
std::cout << 2;
}
int main() {
std::function<void ()> foo = print;
(*foo.target<void (*)()>())(); //prints 3
}
This crashes at the second line of main
:
这在第二行崩溃main
:
#include <functional>
#include <iostream>
void print (int i) {
std::cout << i;
}
int main() {
std::function<void ()> foo = std::bind (print, 2);
(*foo.target<void (*)()>())();
}
I'm really holding the std::function<void ()>
and need to be able to return the function; not just call it. I expect the usage would be something like this:
我真的持有std::function<void ()>
并且需要能够返回该函数;不只是调用它。我希望用法是这样的:
#include <functional>
#include <iostream>
void print (int i) {
std::cout << i;
}
int main() {
Container c (std::bind (print, 2));
//I would expect the original
c.func() (3); //prints 3
if (c.func() == print) /* this is what I'm mostly getting at */
}
Is there any way to get the original function to return it, or an alternative? It does kind of conflict with the return type as well, as void (*)()
matches the bound signature quite nicely.
有没有办法让原始函数返回它,或者替代方法?它也确实与返回类型存在冲突,因为它void (*)()
很好地匹配了绑定签名。
回答by Puppy
This is quite impossible. The whole reason that std::function
exists is that function pointers suck horrifically and should never, ever, be used by anyone, ever again, except for the doomed souls bearing the Burning Standards of HellC interoperation, because they cannot handle functions with state.
这是完全不可能的。std::function
存在的全部原因是函数指针非常糟糕,永远不应该被任何人使用,永远不会再被任何人使用,除了那些承受着地狱C 互操作的燃烧标准的注定灵魂,因为它们无法处理带有状态的函数。
A std::function<void()>
cannot, in the general case, be converted to a void(*)()
. The only reason this works in the first example is because it happensto be a void(*)()
originally.
std::function<void()>
在一般情况下,A不能转换为 a void(*)()
。这在第一个示例中起作用的唯一原因是因为它恰好是一个void(*)()
原始的。
回答by fredbaba
This can be achieved using a little template meta-programming. I recently had use for this while writing a generic C++ wrapper around OpenGL GLUT (which depends on callback function pointers). The approach:
这可以使用一个小的模板元编程来实现。我最近在围绕 OpenGL GLUT(这取决于回调函数指针)编写通用 C++ 包装器时使用了这个。该方法:
- Instantiate an instance of a singleton template type.
- Store your std::function as a member of to the singleton instance
- Invoke your std::function through a static member function (static member functions and free functions have the same type, so the "invoke" function can be used as a free function pointer)
- 实例化单例模板类型的实例。
- 将您的 std::function 存储为单例实例的成员
- 通过静态成员函数调用你的 std::function(静态成员函数和自由函数具有相同的类型,所以“invoke”函数可以用作自由函数指针)
Tested under C++11 on GCC 4.8.
在 GCC 4.8 上在C++11下测试。
#include <unistd.h>
#include <thread>
#include <chrono>
#include <mutex>
#include <functional>
#include <iostream>
#include <cmath>
template <const size_t _UniqueId, typename _Res, typename... _ArgTypes>
struct fun_ptr_helper
{
public:
typedef std::function<_Res(_ArgTypes...)> function_type;
static void bind(function_type&& f)
{ instance().fn_.swap(f); }
static void bind(const function_type& f)
{ instance().fn_=f; }
static _Res invoke(_ArgTypes... args)
{ return instance().fn_(args...); }
typedef decltype(&fun_ptr_helper::invoke) pointer_type;
static pointer_type ptr()
{ return &invoke; }
private:
static fun_ptr_helper& instance()
{
static fun_ptr_helper inst_;
return inst_;
}
fun_ptr_helper() {}
function_type fn_;
};
template <const size_t _UniqueId, typename _Res, typename... _ArgTypes>
typename fun_ptr_helper<_UniqueId, _Res, _ArgTypes...>::pointer_type
get_fn_ptr(const std::function<_Res(_ArgTypes...)>& f)
{
fun_ptr_helper<_UniqueId, _Res, _ArgTypes...>::bind(f);
return fun_ptr_helper<_UniqueId, _Res, _ArgTypes...>::ptr();
}
template<typename T>
std::function<typename std::enable_if<std::is_function<T>::value, T>::type>
make_function(T *t)
{
return {t};
}
int main()
{
std::cout << (void*)get_fn_ptr<0>(make_function(::sin))<<std::endl;
return 0;
}
回答by K-ballo
You can't get a function pointerout of an std::function
, as there may not even be one. It could be a member function pointerinstead, or an objectthat implements operator()
.
你不能得到一个函数指针出来的std::function
,因为有可能甚至是一个。这可能是一个成员函数的指针,而不是,或一个对象实现operator()
。