gpt4 book ai didi

c++ - 使用类绑定(bind)功能调用成员函数

转载 作者:太空宇宙 更新时间:2023-11-04 14:13:23 25 4
gpt4 key购买 nike

如何实现一个非常简单的 boost::bind 版本,它不绑定(bind)参数,但提供了一种在 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 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;
}

上面的实现确实有效,并且会打印:

Foo 1
Bar 2

问题是 my_bind 的两次调用返回不同类型的对象。我怎样才能改变程序,使 my_bind 返回一个只依赖于 A1 的类型。

最佳答案

The problem is that the two invokes of my_bind returns objects of different types. How can I alter the program, such that my_bind will return a type which only depends on A1.

可以用type erasure来做.

简而言之:

  1. 创建具有您喜欢的界面的抽象类。它可能有一些模板参数。 (以下代码中的 AbstractBinder)
  2. 创建实现此接口(interface)的具体 类。具体类可能比接口(interface)有更多的模板参数。 (下面的 Binder 类)
  3. 使用模板构造器创建Holder 类- 创建Concrete 类,但只存储指向它的Abstract 基类的指针。所以,Holder类只有Abstract接口(interface)需要的模板参数,而它的constructor有Concrete类需要的模板参数。 (下面的 BinderHolder 类)

live demo

用法:

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);
}

附言如果您确定您的所有 具体 类都具有相同的大小,那么您可以将堆分配替换为放置在固定大小缓冲区内的新内容,并添加 static_assert 以确保安全。

关于c++ - 使用类绑定(bind)功能调用成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13103462/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com