在另一个模板函数的定义中解压函数参数类型
Unpack function parameter types in the definition of another template function
我正在制作一个 class 模板来编码函数指针。该函数可以有任何结果类型和参数的数量/类型。这是我的:
LPVOID EncodePtr(LPVOID ptr) {
// Encode...
return ptr;
}
LPVOID DecodePtr(LPVOID ptr) {
// Decode...
return ptr;
}
template<class T>
class encoded_ptr {
public:
typedef encoded_ptr<T> _Myt;
encoded_ptr() {
ptr_ = (T*)EncodePtr(nullptr);
}
// Irresponsible?
template<class _OtherType>
encoded_ptr(_OtherType ptr) {
ptr_ = (T*)DecodePtr((LPVOID)ptr);
}
~encoded_ptr() {
ptr_ = (T*)EncodePtr(nullptr);
}
// Makes it possible to call the function directly
template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();
return fn(_Ax...);
}
T* get() const {
return (T*)DecodePtr((LPVOID)ptr_);
}
bool is_set() {
return (get() != nullptr);
}
private:
T* ptr_;
};
它按预期工作。例如:
encoded_ptr<decltype(MessageBoxA)> MsgBox;
MsgBox = &MessageBoxA; // Could also initialize in the constructor
// (HWND)0 is justified by the actual problem in the question
MsgBox((HWND)0, "Test message!", "Test", 0);
第一个问题是括号运算符 ()
的声明方式不允许 Visual Studio 的 IntelliSense 发挥其魔力并给我有关函数参数的提示:
template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();
return fn(_Ax...);
}
我不想使用 (_Args... _Ax)
,而是想解压实际的函数参数,以便 IntelliSense 可以正确给出提示。
当前行为是:
预期行为是:
第二个问题是这样调用函数,编译器不做基本转换,迫使我将NULL
转换为(void*)NULL
,0
转换为(HWND)0
, 等。当使用带有很多参数的函数时,这很烦人。
可能在实现中有一些错误,但我不是模板专家。另外,不知道题名对不对
感谢任何帮助。
编辑:
到目前为止我尝试了什么(@OlegBogdanov 的建议):
template<class T, class... Args>
class encoded_ptr;
template<class T, class... Args>
class encoded_ptr<T(Args...)> {
public:
typedef encoded_ptr<T> _Myt;
using Fptr = T(*)(Args...);
encoded_ptr(Fptr ptr) {
ptr_ = (Fptr)EncodePtr((LPVOID)ptr);
}
// Makes it possible to call the function directly
typename T operator()(Args... _Ax) {
Fptr fn = get();
return fn(std::forward<Args>(_Ax)...);
}
Fptr get() const {
return (T*)DecodePtr((LPVOID)ptr_);
}
bool is_set() {
return (get() != nullptr);
}
private:
Fptr ptr_;
};
结果:无法实例化/使用构造函数:Incomplete type is not allowed
。
编辑:
这是正确的方向,问题是调用约定。
已更改:
class encoded_ptr<T(Args...)>
到 class encoded_ptr<T(__stdcall)(Args...)>
,以及
using Fptr = T(*)(Args...)
到 using Fptr = T(__stdcall*)(Args...)
我正在尝试检测调用约定而不是对其进行硬编码。
我认为您对
的期望
template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();
return fn(_Ax...);
}
错了。它完全忽略了你的目标函数参数列表(你使用了穷人类型的擦除)并传递(我想使用单词 'forwards' 但那是不准确的)无论调用者给出什么。因此 0 in
MsgBox(0, "Test message!", "Test", 0);
被推断为 int
并且您必须将其转换为 HWND
,否则编译器将无法猜测它。
你真正在做的是重新发明 std::function 或它上面的某种包装器。
如果您真的认为 std::function 不足以满足您的需求,您将不得不复制其部分实现,即您至少需要
template<class R, class... Args>
class encoded_ptr; // leaving this undefined
template<class R, class... Args>
class encoded_ptr<R(Args...)> {
using Fptr = R(*)(Args...);
encoded_ptr(Fptr ptr) {
ptr_ = (T*)DecodePtr((LPVOID)ptr);
}
...
在您的类型中捕获参数列表
并且调用运算符将重新使用它而不是随机键入传递的参数:
// this must not be here -> template<class... _Args>
R operator()(Args... _Ax) {
T* fn = get()
return fn(std::forward<Args>(_Ax)...);
}
编辑:
你不能存储但是 T*
了,T
只是一个 return 类型,按 Fptr
存储
我正在制作一个 class 模板来编码函数指针。该函数可以有任何结果类型和参数的数量/类型。这是我的:
LPVOID EncodePtr(LPVOID ptr) {
// Encode...
return ptr;
}
LPVOID DecodePtr(LPVOID ptr) {
// Decode...
return ptr;
}
template<class T>
class encoded_ptr {
public:
typedef encoded_ptr<T> _Myt;
encoded_ptr() {
ptr_ = (T*)EncodePtr(nullptr);
}
// Irresponsible?
template<class _OtherType>
encoded_ptr(_OtherType ptr) {
ptr_ = (T*)DecodePtr((LPVOID)ptr);
}
~encoded_ptr() {
ptr_ = (T*)EncodePtr(nullptr);
}
// Makes it possible to call the function directly
template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();
return fn(_Ax...);
}
T* get() const {
return (T*)DecodePtr((LPVOID)ptr_);
}
bool is_set() {
return (get() != nullptr);
}
private:
T* ptr_;
};
它按预期工作。例如:
encoded_ptr<decltype(MessageBoxA)> MsgBox;
MsgBox = &MessageBoxA; // Could also initialize in the constructor
// (HWND)0 is justified by the actual problem in the question
MsgBox((HWND)0, "Test message!", "Test", 0);
第一个问题是括号运算符 ()
的声明方式不允许 Visual Studio 的 IntelliSense 发挥其魔力并给我有关函数参数的提示:
template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();
return fn(_Ax...);
}
我不想使用 (_Args... _Ax)
,而是想解压实际的函数参数,以便 IntelliSense 可以正确给出提示。
当前行为是:
预期行为是:
第二个问题是这样调用函数,编译器不做基本转换,迫使我将NULL
转换为(void*)NULL
,0
转换为(HWND)0
, 等。当使用带有很多参数的函数时,这很烦人。
可能在实现中有一些错误,但我不是模板专家。另外,不知道题名对不对
感谢任何帮助。
编辑:
到目前为止我尝试了什么(@OlegBogdanov 的建议):
template<class T, class... Args>
class encoded_ptr;
template<class T, class... Args>
class encoded_ptr<T(Args...)> {
public:
typedef encoded_ptr<T> _Myt;
using Fptr = T(*)(Args...);
encoded_ptr(Fptr ptr) {
ptr_ = (Fptr)EncodePtr((LPVOID)ptr);
}
// Makes it possible to call the function directly
typename T operator()(Args... _Ax) {
Fptr fn = get();
return fn(std::forward<Args>(_Ax)...);
}
Fptr get() const {
return (T*)DecodePtr((LPVOID)ptr_);
}
bool is_set() {
return (get() != nullptr);
}
private:
Fptr ptr_;
};
结果:无法实例化/使用构造函数:Incomplete type is not allowed
。
编辑:
这是正确的方向,问题是调用约定。
已更改:
class encoded_ptr<T(Args...)>
到 class encoded_ptr<T(__stdcall)(Args...)>
,以及
using Fptr = T(*)(Args...)
到 using Fptr = T(__stdcall*)(Args...)
我正在尝试检测调用约定而不是对其进行硬编码。
我认为您对
的期望template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();
return fn(_Ax...);
}
错了。它完全忽略了你的目标函数参数列表(你使用了穷人类型的擦除)并传递(我想使用单词 'forwards' 但那是不准确的)无论调用者给出什么。因此 0 in
MsgBox(0, "Test message!", "Test", 0);
被推断为 int
并且您必须将其转换为 HWND
,否则编译器将无法猜测它。
你真正在做的是重新发明 std::function 或它上面的某种包装器。
如果您真的认为 std::function 不足以满足您的需求,您将不得不复制其部分实现,即您至少需要
template<class R, class... Args>
class encoded_ptr; // leaving this undefined
template<class R, class... Args>
class encoded_ptr<R(Args...)> {
using Fptr = R(*)(Args...);
encoded_ptr(Fptr ptr) {
ptr_ = (T*)DecodePtr((LPVOID)ptr);
}
...
在您的类型中捕获参数列表
并且调用运算符将重新使用它而不是随机键入传递的参数:
// this must not be here -> template<class... _Args>
R operator()(Args... _Ax) {
T* fn = get()
return fn(std::forward<Args>(_Ax)...);
}
编辑:
你不能存储但是 T*
了,T
只是一个 return 类型,按 Fptr