我有一个名为Renderer的类,它包含两个回调对象;
library(tidyr)
extract(df, text, into = c("first", "sec"), "(here)_(do)", remove = FALSE)
# var_a var_b text first sec
#1 a 93 foo_bla <NA> <NA>
#2 b 51 here_do here do
#3 c 65 oh_yes <NA> <NA>
#4 d 70 baa <NA> <NA>
#5 e 32 land <NA> <NA>
我想有一个绑定这些回调的公共函数,它是模板化的,需要一个具有两个draw方法的类,每个方法都有它们的有效参数,如下所示:
void (*drawCall)(const sf::Drawable& drawable, const sf::RenderStates& states);
void (*drawPrimCall)(const sf::Vertex* vertices, unsigned int vertexCount,
sf::PrimitiveType type, const sf::RenderStates& states);
然而,正如您可能想象的那样,这不起作用。我还在学习std :: bind,我不确定占位符的使用,我知道我在这里要做的是什么。
我已经尝试在Google上寻找答案但是有点令人生畏,感谢您的帮助!
更新:
好的,所以@Holt给出的答案有效,在更改为std :: function后,我的回调看起来像这样:
template<typename T>
inline void setRenderer(T* instance)
{
using namespace std::placeholders;
drawCall = std::bind(&T::draw, instance, _1, _2);
drawPrimCall = std::bind(&T::draw, instance, _1, _2, _3, _4);
}
现在对于setRenderer方法由于外部库的约束,我还需要传递一个函数引用,就像这样;
std::function<void(const sf::Drawable& drawable, const sf::RenderStates& states)> drawCall_fn;
std::function<void(const sf::Vertex* vertices, unsigned int vertexCount,
sf::PrimitiveType type, const sf::RenderStates& states)> drawPrimCall_fn;
这样当我打电话时,我可以这样做:
template<typename T>
inline void setRenderer(T* instance, void(T::*drawCall)(const sf::Drawable&, const sf::RenderStates&))
{
using namespace std::placeholders;
drawCall_fn = std::bind(drawCall, instance, _1, _2);
}
**注意:我目前只处理drawCall_fn,因为我可以轻松扩展。
UPDATE2:为setRenderer drawCall添加了缺少的参数。
答案 0 :(得分:2)
你无法使用函数指针做你想做的事情,因为你需要&#34;捕获&#34; (使用捕获lambda或使用std::bind
)instance
。您应该使用std::function
:
std::function<void(const sf::Drawable&, const sf::RenderStates&)> drawCall;
std::function<void(const sf::Vertex*, unsigned int,
sf::PrimitiveType, const sf::RenderStates&)> drawPrimCall;
然后,您可以使用lambda或强制&T::draw
的重载分辨率来分配它们:
drawCall = [instance](const sf::Drawable& drawable, const sf::RenderStates& states) {
instance->draw(drawable, states);
});
// Or:
drawCall = std::bind((void (T::*)(const sf::Drawable&, const sf::RenderStates&))&T::draw,
instance, _1, _2);
在这两种情况下,您都必须重新指定参数列表,但是您可以使用小辅助函数来避免这种情况:
template <typename T, typename R, typename... Args, typename... BArgs>
void gbind_mem(std::function<R(Args...)> &fn, R(T::*mfn)(Args...),
T *instance, BArgs&&... args) {
fn = std::bind(mfn, instance, std::forward<BArgs>(args)...);
}
然后你可以使用:
轻松绑定gbind_mem(drawCall, &T::draw, instance, _1, _2);
让编译器完成从drawCall
推断参数的艰苦工作。
答案 1 :(得分:0)
...包含两个回调对象
在C ++中没有&#34;回调对象&#34; 这样的东西。您可能正在寻找的是function pointers或std::function
。对于函数指针,您的语法不正确 - 您需要添加*
:
void (*drawCall)(const sf::Drawable& drawable, const sf::RenderStates& states = sf::RenderStates::Default);
void (*drawPrimCall)(const sf::Vertex* vertices, unsigned int vertexCount, sf::PrimitiveType type,
const sf::RenderStates& states = sf::RenderStates::Default);
然后您就可以设置它们了。例如:
void (*callback)(int);
void real_function(int) { }
int main()
{
callback = &real_function;
}
如果你的&#34;真正的功能&#34;签名与回调不匹配,你应该使用无法隐藏lambda expressions,它可以隐式转换为函数指针,以适应它:
void (*callback)(int);
void real_function(int, float) { }
int main()
{
callback = [](int x){ return real_function(x, 5.f); };
}
如果您在wandbox上提供最少示例,我将能够为您提供更具体的答案。