2012-10-12 29 views
1

我试图揭露传递的std ::功能<bool (int)>通过值

typedef std::function<bool (int)> Filter; 

#include <functional> 

这样的一部分用户可以创建过滤器,并将其传递到我的处理组件。该要求要求处理不能在模板化功能中完成。

我知道在接口上使用STL并不是一种好的做法,因为Filter类型的大小是STL实现相关的。我的替代选项是什么,但对于原始函数指针仿函数接收到仿函数。

+1

你的问题并不清楚,究竟是什么问题?什么都不行,你想做什么? – Xeo

+1

“*我有什么替代选项,但是... *”您可以实现您自己的'std :: function'版本。另外,“*我明白,在接口上使用STL并不是一种好的做法,因为Filter类型的大小是STL实现的依赖。”为什么这一点至关重要?谁在乎'std :: function'有多大?由于对象的大小,您的代码不会失败。接口的唯一问题来自* dll *接口,其中C++基本上是禁止的。 –

+0

@Nicol:有趣的是BigBoss不同意,并准备在界面中使用有限的C++。基本上,他愿意承担一个ABI,允许具有虚拟功能的班级,但不会规定整个标准库的布局。 –

回答

2

大小,如果不是真的很这里重要的,但你是对的,如果有人使用你的库使用不同的实现STL的,那么它将无法使用你的代码,所以有什么其他选择?我会用这个接口(纯虚类):

struct MyCallback { 
    virtual bool filter(int) = 0; 
}; 
class MyImplementation { 
public: 
    ... 
    void set_callbacks(MyCallback*); 
}; 

使用这种架构可以让你的用户使用的C++,并在同一时间的权力,你不依赖于STL!

1

您可以传递函数指针作为std::bind的结果。例如:

typedef std::function<bool (int)> Filter; 

bool Foo(int i) 
{ 
    return i == 0; 
} 

void BarCaller(Filter bar) //pass by value 
{ 
    bar(2); 
} 

Filter bar = std::bind(&Foo, std::placeholders::_1); //now you can pass bar wherever you want 
BarCaller(bar); 
+0

这是多余的,'std :: function'完全有能力处理函数指针。 – Xeo

+0

他试图通过价值传递他们,因为我理解并展示了如何实现它 –

+0

正如我所理解的问题,它确实是关于如何声明'BarCaller',因此它不接受'std :: function ' ,也不是模板参数,也不是裸函数指针。 – jogojapan

1

C风格的回调接口通常通过传递两个值 - 一个函数指针和一个用户数据指针来完成。如果你愿意的话,你可以把它包装在一个结构体中。

所以,如果你想让你的dll界面保持C风格,请提供一种方法来包装std::function。喜欢的东西:

bool c_style_callback(void *userdata, int n) { 
    return (*static_cast<const Filter*>(userdata))(n); 
} 

你可以提供一个头文件中的便利功能,即在调用的dll运行,并提供你真正想要的界面:

inline void register_callback(const Filter &filter) { 
    register_c_style_callback(c_style_callback, static_cast<void*>(&filter)); 
} 

我已经懒的和这呼叫者有责任确保filter只要注册回叫就保持有效。你可以通过动态分配它的副本来修复它,并且在回调被注销时添加代码来检索和释放它(再次,这个代码在调用DLL中运行)。如果取消注册是由调用者发起的,那么您需要某种代表注册回调的句柄。

如果Filter是一个传递给算法的谓词,在返回后不会再使用它,那么懒惰就会带来回报。只有当过滤器无限注册时,您才需要整个机制来管理生命周期。

+0

史蒂夫,我看到的唯一问题是丑陋的看起来 “void *” 我知道这是C风格的回调和无效*是面包和黄油。我希望有更优雅的东西。 +1的努力。谢谢。 – Ram