使用std :: bind时从std :: function获取函数指针

chr*_*ris 10 c++ bind function-pointers c++11

我正在尝试std::function与之配合使用std::bind,但我遇到了一些问题.

这有效:

#include <functional>
#include <iostream>

void print() {
    std::cout << 2;
}

int main() {
    std::function<void ()> foo = print;
    (*foo.target<void (*)()>())(); //prints 3
}
Run Code Online (Sandbox Code Playgroud)

这崩溃在第二行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 (*)()>())();
}
Run Code Online (Sandbox Code Playgroud)

我真的抱着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 */
}
Run Code Online (Sandbox Code Playgroud)

有没有办法让原始函数返回它,或者另类?它确实与返回类型冲突,因为void (*)()匹配绑定签名非常好.

Pup*_*ppy 25

这是不可能的.std::function存在的全部原因是函数指针可怕地吸吮,并且永远不会被任何人使用,除了带有地狱 C 燃烧标准的注定灵魂互操作,因为它们无法处理状态函数.

std::function<void()>在一般情况下,A 不能转换为a void(*)().这在第一个例子中起作用的唯一原因是因为它碰巧void(*)()最初的.

  • *函数指针suck*...只是与`int` sucks或者原始指针相同......它们是构建更高级别构造的低级块.如果没有原始指针和int,你就不会有`std :: string`,没有函数指针你就不会有`std :: function` ... (24认同)
  • @David:不是.你可以在不知道函数指针的情况下实现`std :: function`. (3认同)
  • C 或 C++ 中没有什么“糟糕”的。它的发明在当时是非常有意义的,它是为了解决目前仍然相关的实际问题。就像我们创造的一切一样。 (2认同)

fre*_*aba 14

这可以使用一点模板元编程来实现.我最近在编写围绕OpenGL GLUT的通用C++包装器时使用了它(它依赖于回调函数指针).该方法:

  1. 实例化单例模板类型的实例.
  2. 将std :: function存储为singleton实例的成员
  3. 通过静态成员函数调用std :: function(静态成员函数和自由函数具有相同的类型,因此"invoke"函数可以用作自由函数指针)

在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;
}
Run Code Online (Sandbox Code Playgroud)

  • 当多个线程设置单例类的 `std::function` 时,此解决方案不适用于多线程。 (2认同)
  • 它也不能以可重入的方式工作,或者实际上,在任何远程复杂的场景中都不能工作。这是不可靠的。 (2认同)

K-b*_*llo 7

你不能得到一个函数指针出来的std::function,因为有可能甚至是一个.它可以是成员函数指针,也可以是实现的对象operator().