使用类绑定功能调用成员函数 如何实现一个非常简单的Booo::Boin版本,它不绑定参数,而是提供一种在C++类中调用成员函数的方法。
这是我的第一次尝试:使用类绑定功能调用成员函数 如何实现一个非常简单的Booo::Boin版本,它不绑定参数,而是提供一种在C++类中调用成员函数的方法。,c++,C++,这是我的第一次尝试: #include <iostream> struct Foo { void x(int i) { std::cout << "Foo " << i << std::endl; } }; struct Bar { void y(int i) { std::cout << "Bar " << i << std::endl; } }; template<typename
#include <iostream>
struct Foo {
void x(int i) { std::cout << "Foo " << i << std::endl; }
};
struct Bar {
void y(int i) { std::cout << "Bar " << i << std::endl; }
};
template<typename A1, typename I, typename M>
struct Binder {
Binder(I i, M m) : i_(i), m_(m) { }
void operator()(A1 a1) {
(i_->*m_)(a1);
}
I i_;
M m_;
};
template<typename A1, typename I, typename M>
Binder<A1, I, M> my_bind(I i, M m) {
return Binder<A1, I, M>(i, m);
}
int main(int argc, const char *argv[])
{
Foo foo;
Bar bar;
Binder<int, Foo*, void (Foo::*)(int)> b1 = my_bind<int>(&foo, &Foo::x);
Binder<int, Bar*, void (Bar::*)(int)> b2 = my_bind<int>(&bar, &Bar::y);
b1(1);
b2(2);
return 0;
}
问题是my_bind的两个调用返回不同类型的对象。如何修改程序,使我的_绑定返回一个仅依赖于A1的类型
问题是my_bind的两个调用返回不同类型的对象。如何修改程序,使我的_绑定返回一个仅依赖于A1的类型
这是可能的
简言之:
使用您喜欢的接口创建抽象类。它可能有一些模板参数。下面代码中的AbstractBinder
创建实现此接口的具体类。具体类的模板参数可能多于接口。下面是活页夹等级
使用模板构造函数创建Holder类-它创建具体类,但只存储指向其基本抽象类的指针。所以,Holder类只有抽象接口所需的模板参数,而其构造函数具有具体类所需的所有其余模板参数。下面是BinderHolder类
用法:
int main()
{
Foo foo;
Bar bar;
BinderHolder<int> b1 = my_bind<int>(&foo, &Foo::x);
BinderHolder<int> b2 = my_bind<int>(&bar, &Bar::y);
b1(1);
b2(2);
}
完整代码:
template<typename A1>
struct AbstractBinder
{
virtual void call(A1 a1)=0;
virtual AbstractBinder<A1> *clone()=0;
virtual ~AbstractBinder(){}
};
template<typename A1, typename I, typename M>
struct Binder : AbstractBinder<A1>
{
Binder(I i, M m) : i_(i), m_(m) { }
void call(A1 a1)
{
(i_->*m_)(a1);
}
virtual AbstractBinder<A1> *clone()
{
return new Binder(*this);
}
I i_;
M m_;
};
template<typename A1>
class BinderHolder
{
AbstractBinder<A1> *ptr;
BinderHolder &operator=(const BinderHolder&);
public:
template<typename I, typename M>
BinderHolder(I i, M m)
: ptr(new Binder<A1,I,M>(i,m))
{
}
BinderHolder(const BinderHolder &rhs)
: ptr(rhs.ptr->clone())
{
}
~BinderHolder()
{
delete ptr;
}
void operator()(A1 a1)
{
ptr->call(a1);
}
};
template<typename A1, typename I, typename M>
BinderHolder<A1> my_bind(I i, M m) {
return BinderHolder<A1>(i, m);
}
#include <iostream>
struct Foo {
void x(int i) { std::cout << "Foo " << i << std::endl; }
};
struct Bar {
void y(int i) { std::cout << "Bar " << i << std::endl; }
};
int main()
{
Foo foo;
Bar bar;
BinderHolder<int> b1 = my_bind<int>(&foo, &Foo::x);
BinderHolder<int> b2 = my_bind<int>(&bar, &Bar::y);
b1(1);
b2(2);
}
另外,如果您确信所有具体类都具有相同的大小,那么您可以将堆分配替换为在固定大小的缓冲区中放置新的内容,并添加静态断言以确保安全。我认为您最好使用std::mem\u fn。。。或者,您是否愿意绑定参数,例如对象?我已经开始研究这一点,因为它需要在嵌入式应用程序中,C++环境不支持异常或标准库。所以,std::men\u fn在我的目标系统上是不可用的…当我想到这一点时,我需要了解的是更多的boost::function实现。我没有看到您的第二个要求,即,您希望类型擦除封闭类。。。我发现您确实想要在类中绑定对象。要删除对象类型,您需要使用std::function的道德等价物,它在内部使用一个小的继承层次结构:您可能也应该制作这些独立的工具。你能使用C++ 2011,特别是可变模板吗?没有可变模板,这有点像一个打字练习。没有c++2011,也没有可变模板。但只要我只想支持一个论点,这就不应该是问题。
template<typename A1>
struct AbstractBinder
{
virtual void call(A1 a1)=0;
virtual AbstractBinder<A1> *clone()=0;
virtual ~AbstractBinder(){}
};
template<typename A1, typename I, typename M>
struct Binder : AbstractBinder<A1>
{
Binder(I i, M m) : i_(i), m_(m) { }
void call(A1 a1)
{
(i_->*m_)(a1);
}
virtual AbstractBinder<A1> *clone()
{
return new Binder(*this);
}
I i_;
M m_;
};
template<typename A1>
class BinderHolder
{
AbstractBinder<A1> *ptr;
BinderHolder &operator=(const BinderHolder&);
public:
template<typename I, typename M>
BinderHolder(I i, M m)
: ptr(new Binder<A1,I,M>(i,m))
{
}
BinderHolder(const BinderHolder &rhs)
: ptr(rhs.ptr->clone())
{
}
~BinderHolder()
{
delete ptr;
}
void operator()(A1 a1)
{
ptr->call(a1);
}
};
template<typename A1, typename I, typename M>
BinderHolder<A1> my_bind(I i, M m) {
return BinderHolder<A1>(i, m);
}
#include <iostream>
struct Foo {
void x(int i) { std::cout << "Foo " << i << std::endl; }
};
struct Bar {
void y(int i) { std::cout << "Bar " << i << std::endl; }
};
int main()
{
Foo foo;
Bar bar;
BinderHolder<int> b1 = my_bind<int>(&foo, &Foo::x);
BinderHolder<int> b2 = my_bind<int>(&bar, &Bar::y);
b1(1);
b2(2);
}