为了跟进霍华德的好回答,让我声明一下,最后我得出的结论是,将 sendBarToID 函数模板化并没有真正按照我希望的方式改进设置的逻辑。由于无论如何我们都必须绑定(),所以没有理由先绑定然后取消绑定占位符,我们不妨将所有内容绑定到位。这是非模板版本:
void sendBarToID_15(std::function<void(int)> f)
{
f(15);
}
void yum()
{
// No avoiding this in the presence of overloads
void (Foo::*mfp)(int, int, int) = &Foo::bar;
sendBarToID_15(std::bind(mfp, this, std::placeholder::_1, 17, 29));
}
我希望可变参数模板解决方案能够以某种方式使客户端代码更简单,但现在我看不出它怎么能比这更简单。可变参数#define 宏负责其余部分。
感谢您的贡献!
更新:好的,这就是我最终想出的,这要归功于预处理器宏:
#include <functional>
#include <iostream>
class Baz;
class Foo
{
void bar(int ID, const int &, int)
{ std::cout << "v1 called with ID " << ID << "\n"; }
void bar(int ID)
{ std::cout << "v2 called with ID " << ID << "\n"; }
void bar(int ID, double, float, void(Baz::*)()) const
{ std::cout << "v3 called with ID " << ID << "\n"; }
void innocent(int ID, double)
{ std::cout << "innocent called with ID " << ID << "\n"; }
void very_innocent(int ID, double) const
{ std::cout << "very innocent called with ID " << ID << "\n"; }
template<int ID> void sendBarToID(std::function<void(int)> refB) { refB(ID); }
template<int ID> void sendConstBarToID(std::function<void(int)> refB) const { refB(ID); }
#define MAKE_CALLBACK(f, ...) std::bind(&Foo::f, this, std::placeholders::_1, __VA_ARGS__)
#define MAKE_EXPLICIT_CALLBACK(g, ...) std::bind(g, this, std::placeholders::_1, __VA_ARGS__)
#define MAKE_SIGNED_CALLBACK(h, SIGNATURE, ...) MAKE_EXPLICIT_CALLBACK(static_cast<void (Foo::*)SIGNATURE>(&Foo::h), __VA_ARGS__)
#define MAKE_CONST_SIGNED_CALLBACK(h, SIGNATURE, ...) MAKE_EXPLICIT_CALLBACK(static_cast<void (Foo::*)SIGNATURE const>(&Foo::h), __VA_ARGS__)
public:
void gobble()
{
double q = .5;
int n = 2875;
void(Baz::*why)();
sendBarToID<5>(MAKE_CALLBACK(innocent, q));
sendConstBarToID<7>(MAKE_CALLBACK(very_innocent, q));
// sendBarToID<11>(MAKE_SIGNED_CALLBACK(bar, (int))); // can't do, too much commas
sendBarToID<13>(MAKE_SIGNED_CALLBACK(bar, (int, const int &, int), n, 1729));
sendConstBarToID<17>(MAKE_CONST_SIGNED_CALLBACK(bar, (int, double, float, void(Baz::*)()), q, q, why));
}
void yum() const
{
double q = .5;
int n = 2875;
void(Baz::*why)();
sendConstBarToID<2>(MAKE_CALLBACK(very_innocent, q));
// sendBarToID<-1>(MAKE_CALLBACK(innocent, q)); // Illegal in const function
sendConstBarToID<3>(MAKE_CONST_SIGNED_CALLBACK(bar, (int, double, float, void(Baz::*)()), q, q, why));
}
};
int main()
{
Foo foo;
foo.yum();
foo.gobble();
}
有一个不便之处:我需要为常量和非常量成员函数定义两个单独的函数和宏。此外,我无法处理空参数列表 (Foo::bar(int))。