我正在尝试在类中创建一个功能字段,用户可以将其设置为任意 lambda 函数,然后将其作为成员函数进行调用。该字段基本上是一个 std::function
,但在调用其 operator()
时应隐式传递 this
作为其第一个参数。
假设 Event
类做了我想要实现的事情:
template <typename... Args> class Event;
然后我希望能够写:
class Container {
public:
Event<int> func = this ;
};
int main() {
Container c;
c.func = [](Container* This, int x) {
.......
};
c.func(42);
return 0;
}
我希望能够像 std::function
那样分配其他类似函数的对象(例如带有 operator()
的结构)。
我认为如果我将 Event
实现为 std::function
的派生物,并导入它的 operator=
定义,它就会起作用.但似乎有些歧义。
这是我写的:
#include <functional>
class Container;
template <typename... Args>
class Event : public std::function<void(Container*, Args...)> {
private:
typedef std::function<void(Container*, Args...)> ParentType;
Container* This;
public:
using ParentType::operator=;
Event(Container* This) : This(This) {}
void operator()(Args... args) {
ParentType::operator()(This, args...);
}
};
不幸的是,我在尝试编译它时收到一些警告和错误:
event.h(17): warning C4522: 'Event<int>' : multiple assignment operators specified
1> container.h(6) : see reference to class template instantiation 'Event<int>' being compiled
1>main.cpp(19): error C2666: 'std::function<void (Container *,int)>::operator =' : 3 overloads have similar conversions
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(632): could be 'std::function<void (Container *,int)> &std::function<void (Container *,int)>::operator =(const std::function<void (Container *,int)> &)'
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(642): or 'std::function<void (Container *,int)> &std::function<void (Container *,int)>::operator =(std::function<void (Container *,int)> &)'
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(674): or 'std::function<void (Container *,int)> &std::function<void (Container *,int)>::operator =(std::function<void (Container *,int)> &&)'
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(700): or 'std::function<void (Container *,int)> &std::function<void (Container *,int)>::operator =(std::nullptr_t)'
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(685): or 'std::function<void (Container *,int)> &std::function<void (Container *,int)>::operator =<main::<lambda_744a2f58777db28ba36902fcfe375a8a>>(_Fx &&)'
1> with
1> [
1> _Fx=main::<lambda_744a2f58777db28ba36902fcfe375a8a>
1> ]
1> while trying to match the argument list '(Event<int>, main::<lambda_744a2f58777db28ba36902fcfe375a8a>)'
...我迷路了。
我应该只“导入”继承的 operator=
之一吗?实现我自己的并以某种方式调用其中之一?
最佳答案
调用父 operator=
对于多态对象来说是个糟糕的主意。请记住,function
是多态的。总的来说,我认为您应该更喜欢聚合而不是派生,因为那样您可以更好地控制调用什么以及何时调用,如下所示:
template <typename... Args>
class Event {
public:
typedef std::function<void( Container*, Args... )> ParentType;
ParentType inner;
Container* This;
Event( Container* This ) : This( This ) {}
void operator()( Args... args ) {
inner( This, args... );
}
};
int main() {
Container c;
c.func.inner = []( Container* This, int x ) {
};
c.func( 42 );
return 0;
}
当然,如果您不想公开Event
的内部结构,您可以将它们设为私有(private)并提供适当的设置函数。
关于c++ - Lambda 成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22453980/