我想注册回调函数,并将它们存储在向量中以调用它们。还应该允许使用成员函数作为回调函数。
我最初的方法是以下列方式使用strBefore
:
<functional>
由于编译器无法推导出参数类型,因此无法正常工作。它仅在我明确指定类型时才有效:#include <functional>
#include <vector>
#include <iostream>
std::vector<std::function<void()>> functions;
struct Foo {
void Bar() {
std::cout << "Hello" << std::endl;
}
};
template<class T>
void Register( T* obj, std::function<void(T*)> function ) {
functions.push_back( std::bind( function, obj ) );
}
void main(){
Foo foo;
Register(&foo, &Foo::Bar);
}
。这不是我想要的,所以我尝试使用旧的函数指针:
Register<Foo>(&foo, &Foo::Bar);
它有效。由于我不喜欢这种形式的函数指针,我为Memberfunction指针创建了一个类型:
template<class T>
void Register( T* obj, void(T::* function)() ) {
functions.push_back( std::bind( function, obj ) );
}
这很好用。但是现在我想用一个参数来支持函数,因为我不想为每个我希望再次使用模板的参数类型指定一个Memberfunction。
template<class Owner>
using Memberfunction = void( Owner::* )();
template<class T>
void Register( T* obj, Memberfunction<T> function ) {
functions.push_back( std::bind( function, obj ) );
}
到目前为止这项工作还不错,但我不想为一个参数或没有参数指定成员函数,所以我想使用template<class Owner, class Param>
using Memberfunction = void( Owner::* )( Param );
template<class T>
void Register( T* obj, Memberfunction<T,float> function ) {
using namespace std::placeholders;
functions.push_back( std::bind( function, obj, _1 ) );
}
作为void
的第二个参数,但这会导致内部编译错误,所以我猜这不起作用。
有趣的是Memberfunction
会导致以下错误:
Memberfunction<Foo,void> bar = &Foo::Bar;
现在问我的问题:
以某种方式可以使用cannot convert from 'void (__thiscall Foo::* )(void)' to 'void (__thiscall Foo::* )(void)'
吗?
如果这不起作用,我可以避免必须指定至少两个成员函数类型吗?
提前感谢您的帮助。
答案 0 :(得分:2)
您可以通过在结构中隐藏function<void(T*)
的类型来完成此工作。这避免了非推断上下文的问题:
template<typename T>
struct void_fn_type
{
using type = std::function<void(T)>;
};
template<class T>
void Register(T* obj, typename void_fn_type<T*>::type function) {
functions.push_back( std::bind( function, obj ));
}
我觉得不得不建议使用lambda而不是std::bind
(修改:不确定它是否是此方案中未推断的上下文。可能是Foo::Bar
只能转换为std::function<void(Foo*)>
这一事实的问题)
答案 1 :(得分:1)
有趣的是
innerHTML
会导致以下错误:Memberfunction<Foo,void> bar = &Foo::Bar;
那是因为你的编译器给你一个错误的错误信息。代码本身无效,但它与类型cannot convert from 'void (__thiscall Foo::* )(void)' to 'void (__thiscall Foo::* )(void)'
的创建有关。您可以将Memberfunction<Foo,void>
用作函数的参数列表,仅用于它不依赖的特殊情况。来自[dcl.fct]:
由非依赖类型
void
的单个未命名参数组成的参数列表等效于空参数列表。除了这种特殊情况,参数不应具有 cvvoid
类型。
我可以写出void
类型。但我不能写类型void(void)
。在这种情况下,您尝试使用从属template <class T> using F = void(T); F<void>
类型作为参数列表来创建指向成员的指针函数。
但你不需要void
。只需修改别名声明即可允许传入任何参数:
std::function
那就是说,这没有多大意义:
template<class Owner, class... Params>
using Memberfunction = void( Owner::* )( Params... );
Memberfunction<Foo> bar = &Foo::Bar;
template<class T>
void Register( T* obj, Memberfunction<T,float> function ) {
using namespace std::placeholders;
functions.push_back( std::bind( function, obj, _1 ) );
}
是functions
的容器 - 即,nullary函数对象 - 但std::function<void()>
是一个需要一个参数的函数。这不会奏效。你也必须通过浮动:
std::bind(function, obj, _1)
否则它不会是无效的。或者,更一般地说:
template<class T>
void Register( T* obj, Memberfunction<T,float> function, float var ) {
functions.push_back( std::bind( function, obj, var ) );
}