1

我将使用一个我遇到问题的例子,但我会尽量保持主题尽可能通用。我有一个函数,它接受一个类型的参数void (*)(),我想从另一个接受输入参数的函数绑定它std::bind。这可以做到吗?下面是我在 freeglut 中的例子:

(我读过这个:将 std::bind 转换为函数指针,这确认以下内容不起作用 - 解决方法???)

void callback(Obj obj1, Obj obj2, Obj obj3)
{
  // do something with the object and display data
}

// meanwhile, in main()
std::function<void ()> callbackFunctor = &std::bind(callback, obj1, obj2, obj3);

// the following doesn't work because glutIdleFunc expects a type void (*)()
glutIdleFunc(callbackFunctor );

除了 make和globals 之外obj1,通常如何将信息传递到 GLUT 中的空闲回调?obj2obj3

4

2 回答 2

1

全局变量(更好static的,仅对一个文件可见),可能链接到折叠函数调用中,或者在被调用函数中使用例如set_/调用的单独系统。get_userdata(function_address)

问题是,如果您的回调总是使用相同的参数调用,为什么要以这种方式传递它们?GLUT API 没有这个,因为它没有用。

无论如何,没有 API 可以涵盖您所有可能的请求。如果有些东西不合适,你必须重新考虑你在做什么,如果你确定,在给定的 API 之上实现你自己的解决方法。

于 2013-10-28T06:08:14.663 回答
1

您不能将 a 转换std::function函数指针(您可以做相反的事情)。

我环顾四周,发现这篇关于如何存储可变参数包的帖子。

如果您稍微修改该代码,使成员成为static,它可能对您有用:

namespace helper {
    template <std::size_t... Ts>
    struct index {};

    template <std::size_t N, std::size_t... Ts>
    struct gen_seq : gen_seq<N - 1, N - 1, Ts...> {};

    template <std::size_t... Ts>
    struct gen_seq<0, Ts...> : index<Ts...> {};
}

template <typename... Ts>
class Action {
private:
    static std::function<void (Ts...)> f_;
    static std::tuple<Ts...> args_;
public:
    template <typename F, typename... Args>
    static void setAction(F&& func, Args&&... args) {
        f_ = std::forward<F>(func);
        args_ = std::make_tuple(std::forward<Args>(args)...);
    }

    template <typename... Args, std::size_t... Is>
    static void func(std::tuple<Args...>& tup, helper::index<Is...>) {
        f_(std::get<Is>(tup)...);
    }

    template <typename... Args>
    static void func(std::tuple<Args...>& tup) {
        func(tup, helper::gen_seq<sizeof...(Args)>{});
    }

    static void act() {
        func(args_);
    }
};

// Init static members.
template <typename... Ts> std::function<void (Ts...)> Action<Ts...>::f_;
template <typename... Ts> std::tuple<Ts...> Action<Ts...>::args_;

使用上面的代码,您可以将具有在运行时指定的任意参数的任何函数或函数对象存储为 an Action,并使用其不带参数的静态成员函数act()来调用具有先前指定参数的存储函数。

act()可以转换为它void (*)()可以传递给您的回调函数。

以下应该有效:

auto someCallable = [] (int x) { std::cout << "Number " << x << std::endl };
Action<int>::setAction(someCallable, 1); // Pass func and parameters.
glutIdleFunc(Action<int>::act);
于 2013-10-28T17:38:23.467 回答