(注:正如应该已经从标签清楚,这是严格C++ 03是的,我知道,拉姆达使得这一切痛苦消失(在新带来的种类,我打赌),但这是一个嵌入式系统,具有90年代的操作系统版本,我被告知应该很高兴我有一个C++ 03编译器(GCC4.1.x,BTW)或C++因此,请放弃发布C++ 11解决方案,不需要蹭它,真的。
另外,std::bind()
,std::function()
等当然实际上在std::tr1
,但我编辑了tr1
前缀,因为我认为它在代码中只增加了噪声。)如何用std :: bind做到这一点?
我有一些类似服务器的东西,我需要注册的功能,我需要调整它们来调用一些对象的相似但略有不同的功能。这些函数有不同的参数列表。服务器“知道”,当我尝试注册一个函数时,它只接受一个带有正确签名的函数(正如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;}
};
这实际工作,但在现实中有这样多的功能,做这个作为一个乏味的copy'n'paste努力侮辱我的尊严感和产生臭味的代码。由于所有这些函数的功能完全相同,唯一不同的是它们调用的函数以及它们具有或不具有的参数,所以我应该能够将它们折叠成一个参数化函数,从而将差异隐藏在std::bind()
之后。如果做不到这一点,我首先对没有任何参数的所有功能(如foo()
)这样做,这是绝大多数。
int call_it(std::function<bool()> f) {return f() ? MAGIC_OK : MAGIC_FAILED;}
,并绑定在X
相应的函数作为参数传递给它:
所以我通过一个单一功能Y::call_it
,做繁琐的部分想航线的foo()
样功能的所有调用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
的模板化胆量,它可以让一个成年男子流下眼泪,至少应该让他的家庭缩水一年。
所以在我之前kill myself out of sheer frustration和孤儿我的孩子 - 我怎么能这样做?
我从来没有使用过std :: bind。那是为了认罪。但是,你不想'register_call(std :: bind(&Y :: call_it,this,std :: bind(ptmf,std :: ref(x_)));'? –
rici
@rici:当然,你是对的。[我已经看到了这个我自己](http://chat.stackoverflow.com/transcript/10?m=6878122#6878122。)它只是我一直在撞我的头撞墙小时,而这只是1001号中间的混乱状态,试图让它工作,这是当我决定要问这个问题的时候,然而,问题是我不能以另一种方式工作,_sigh._ – sbi
我想这就是为什么我从来没有使用过std :: bind模板metadebugging是疯狂的,或者它让你疯狂,这可能是为什么所有标准库实现都不合标准。祝你好运! – rici