64,683
社区成员
发帖
与我相关
我的任务
分享
#include <cstdio>
#include <functional>
#include <windows.h>
class TEST
{
public:
auto Get_Func() -> std::function <int __stdcall (char)>;
private:
int CALLBACK call_func(char);
};
auto TEST::Get_Func() -> std::function <int __stdcall (char)>
{
return std::bind (&TEST::call_func, this, std::placeholders::_1);
}
int CALLBACK TEST::call_func(char a)
{
return a <= '9' && a >= '0';
}
int main_func(std::function <int __stdcall (char)> abc, char c)
{
return abc (c);
}
int main()
{
TEST t;
return main_func(t.Get_Func(), getchar ());
}
[Error] return type 'class std::function<int(char)>' is incomplete
LRESULT WndProc (HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK G_WndProc (HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WinApp <T>::G_WndProc (HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
WinApp* pThis = nullptr;
LRESULT lRet = 0;
if (Message == WM_NCCREATE)
{
auto pcs = reinterpret_cast <LPCREATESTRUCT> (lParam);
pThis = reinterpret_cast <WinApp*> (pcs -> lpCreateParams);
SetWindowLongPtr (hwnd, GWLP_USERDATA, reinterpret_cast <LONG_PTR> (pThis));
lRet = DefWindowProc (hwnd, Message, wParam, lParam);
}
else
{
pThis = reinterpret_cast <WinApp*> (GetWindowLongPtr (hwnd, GWLP_USERDATA));
if (pThis)
{
lRet = pThis -> WndProc (hwnd, Message, wParam, lParam);
}
else
{
lRet = DefWindowProc (hwnd, Message, wParam, lParam);
}
}
return lRet;
}
果然是不需要__stdcall的,看来是我太固执了……LRESULT CALLBACK WndProc (HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
由于这个函数可以监听消息,程序有时候需要根据这个消息做出变化,所以这个函数理应不该被完全封装,所以我才想到传入一个外部类的函数指针和一个外部类的对象来实现具体的代码细节,后来发现需要使用function,大概就是下面这样:
LRESULT CALLBACK WndProc (HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
if (call_func) // call_func 是 std::function <LRESULT /* CALLBACK */ (HWND, UINT, WPARAM, LPARAM)>;
call_func (hwnd, Message, wParam, lParam); // 转发给外部类处理
switch (Message)
{
// ...
}
return 0;
}
会不会这个__stdcall 只需要出现在原有的消息队列就可以了?然后转发的函数是不需要的?[Error] template argument 1 is invalid
应该是function类模板中std::function <int __attribute__((__stdcall__)) (char)>
编译器将__attribute__((__stdcall__))括号内的__stdcall__当成了形参,请问这个是否有解决方案?#include <cstdio>
#include <functional>
#include <windows.h>
class TEST
{
public:
auto Get_Func() -> int (TEST::*) (char);
private:
int CALLBACK call_func(char);
};
auto TEST::Get_Func() -> int (TEST::*) (char)
{
return & call_func;
}
int CALLBACK TEST::call_func(char a)
{
return a <= '9' && a >= '0';
}
int main_func(int (TEST::* abc) (char), TEST* t, char c)
{
return (t ->* abc) (c);
}
int main ()
{
TEST t;
return main_func(t.Get_Func(), &t, getchar ());
}
但是由于this指针的原因,return & call_func; 这句代码是非法的 (虽然它能在DEV的 64位编译通过),而且我也不想再写一个自定义类适配器,(比如这篇文章讲的),于是我最终才采用了function的写法……[Error] could not convert 'std::bind(_Func&&, _BoundArgs&& ...) [with _Func = int (TEST::*)(char); _BoundArgs = {TEST*, const std::_Placeholder<1>&}; typename std::_Bind_helper<std::__or_<std::is_integral<typename std::decay<_Tp>::type>, std::is_enum<typename std::decay<_Tp>::type> >::value, _Func, _BoundArgs ...>::type = std::_Bind<std::_Mem_fn<int (TEST::*)(char)>(TEST*, std::_Placeholder<1>)>]((* &((TEST*)this)), (* & std::placeholders::_1))' from 'std::_Bind_helper<false, int (TEST::*)(char), TEST*, const std::_Placeholder<1>&>::type {aka std::_Bind<std::_Mem_fn<int (TEST::*)(char)>(TEST*, std::_Placeholder<1>)>}' to 'std::function<int(char)>'
这下感觉更懵逼了
f.target<int(__stdcall*)(char)>();
//or
typedef int (__stdcall* YourFuncType)(char);
f.target<YourFuncType>();
//上面 f 的类型为std::function<int(char)>, 且其实际存储的函数指针类型符合int(__stdcall*)(char),target()才能返回值,否则返回null
也可以使用其target_type函数来判断其类型
f.target_type() == typeid(int(__stdcall*)(char));
另外,我简单表达一下function的实现原理。有助于你理解它的模板形参。
template<typename T>
struct MyFunction; //前向声明;
//////////////////////////////////////////////////////////////////////////
//为各种情况特化;
//函数别名:
template<typename Ret, typename... Args>
struct MyFunction< Ret(Args...)>、
{
//...
}
//函数指针:
template<typename Ret, typename... Args>
struct MyFunction<Ret(*)(Args...)> : MyFunction<Ret(Args...)> {};
//stdcall 版:
template<typename Ret, typename... Args>
struct MyFunction<Ret(__stdcall *)(Args...)> : MyFunction<Ret(Args...)> {};
//...其他各种调用约定...略
//各种类方法(成员函数):
#define METHOD_TRAITS(...) \
template <typename Ret, typename Cx, typename... Args> \
struct MyFunction<Ret(Cx::*)(Args...) __VA_ARGS__> : MyFunction<Ret(Args...)> {};
METHOD_TRAITS()
METHOD_TRAITS(const) //const成员函数;
METHOD_TRAITS(volatile)
METHOD_TRAITS(const volatile)
// 对拥有 cv 限定符的类型的特化;
template<typename T>
struct MyFunction<const T> : MyFunction<T> {};
template<typename T>
struct MyFunction<volatile T> : MyFunction<T> {};
// 对拥有引用限定符的类型的特化;
template<typename T>
struct MyFunction<T&> : MyFunction<T> {};
template<typename T>
struct MyFunction<T&&> : MyFunction<T> {};
用户在使用MyFunction的时候,实际的实参是啥,自然就能找到对应的版本。 而不需要用户手动传入实参的准确类型。