(注意: 从标签中应该已经清楚了,这严格来说是 C++03。 是的,我知道,lambda 让所有这些痛苦消失了(并且带来了新的种类,我敢打赌),但这是一个嵌入式系统,使用 90 年代的操作系统版本,我被告知我应该很高兴我有一个 C++03 编译器(GCC4.1.x,BTW)或 C++ 编译器。所以请不要发布 C++11解决方案。真的不需要把它擦进去。当然
,当然std::bind()
,std::function()
等等实际上是在 中std::tr1
,但我编辑了 tr1
前缀,因为我认为它主要只是给代码增加了噪音。)
我有一些类似服务器的东西需要注册函数,我需要调整它们以调用某些对象的类似但略有不同的函数。这些函数有不同的参数列表。服务器“知道”,当我尝试注册一个函数时,它只接受一个具有正确签名的函数(std::function
即,根据需要正确),这取决于作为模板参数传入的一些魔术标签。
这是代码的草图:
// this I just use
class server {
public:
template<unsigned int MagicTag>
bool register_call(typename some_traits_type<MagicTag>::func_type);
};
// this needs to be called from the server
class X {
public:
bool foo();
bool bar(std::string&);
bool baz(int);
};
// this is the glue
class Y {
public:
Y(X& x) : x_(x) {
register_call<MAGIC_FOO>(&Y::foo );
register_call<MAGIC_BAZ>(&Y::bar, _1);
register_call<MAGIC_FBZ>(&Y::baz, _1);
}
private:
X& x_;
template<unsigned int MagicTag, typename Function>
bool register_call(Function function) {
somewhere->register_call<MagicTag>(std::bind( function
, this ));
}
template<unsigned int MagicTag, typename Function, typename PlaceHolder1>
bool register_call(Function function, PlaceHolder1 place_holder1) {
somewhere->register_call<MagicTag>(std::bind( function
, this
, place_holder1 ));
}
int foo() {return x_.foo() ? MAGIC_OK : MAGIC_FAILED;}
int bar(std::string& s) {return x_.bar(s) ? MAGIC_OK : MAGIC_FAILED;}
int baz(int i) {return x_.baz(i) ? MAGIC_OK : MAGIC_FAILED;}
};
这确实有效,但实际上有更多的功能,这样做是一种乏味的复制粘贴工作,侮辱了我的尊严感并产生了臭代码。由于所有这些函数的作用完全相同,唯一的区别是它们调用的函数以及它们有或没有要传递的参数,我应该能够将它们折叠成一个参数化函数,将差异隐藏在std::bind()
. 如果做不到这一点,我决定首先对所有没有任何参数的函数(如foo()
)执行此操作,这是绝大多数。
所以我想通过一个完成繁琐部分的函数来路由所有foo()
-like 函数的调用:X
Y::call_it
int call_it(std::function<bool()> f) {return f() ? MAGIC_OK : MAGIC_FAILED;}
并将适当的函数X
作为参数绑定到它:
register_call<MAGIC_FOO>(&X::foo); // note the X!
// (this is wrong)
somewhere->register_call<MagicCode>( std::bind( std::bind( &Y::call_it
, this
, function )
, std::ref(x_) );
显然,这是错误的,我解决此问题的所有其他尝试也是如此。(我现在才玩std::bind()
了 10 周,所以请多多包涵)。最后,我迷失在一个令人难以置信的迷宫中,这些错误信息来自std::function
模板化的胆量,这些信息会让一个成年人落泪,至少应该养活一个心理医生和他的大家庭一年。
因此,在我出于纯粹的挫败感而自杀并使我的孩子成为孤儿之前——我该怎么做呢?