我将使用我遇到问题的示例,但我会尝试尽可能保持主题的通用性。我有一个函数,它接受void (*)()
类型的参数,我希望使用std::bind
从另一个函数绑定输入参数。可以这样做吗?以下是我在freeglut上的例子:
(我读过这个:convert std::bind to function pointer,它确认以下内容不起作用 - 解决方法???)
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 );
除了制作obj1
,obj2
和obj3
全局变量外,如何将信息传递到GLUT中的空闲回调?
答案 0 :(得分:1)
Globals(更好的static
个,仅对一个文件可见),可能链接到折叠函数调用,或者单独的系统,例如, <{1}} / set_
在被叫函数中调用。
问题是,如果您的回调始终使用相同的参数调用,为什么要以这种方式传递它们? GLUT API没有这个,因为它没有用处。
无论如何,没有API可以涵盖您所有可能的请求。如果某些东西不适合,你必须重新考虑你在做什么,如果你确定,在给定的API之上实现你自己的解决方法。
答案 1 :(得分:1)
您无法将std::function
转换为函数指针(您可以执行相反的操作)。
我正在四处寻找,我发现了this post如何存储可变背包。
如果您稍微修改该代码,使成员静态,它可能对您有用:
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_;
使用上面的代码,您可以将在运行时指定的任意参数作为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);