提问人:haton 提问时间:11/3/2023 最后编辑:haton 更新时间:11/3/2023 访问量:38
如何在可变参数函数包装器中强制类型提升?
How to force type promotion in a variadic function wrapper?
问:
我正在编写一个包装器来调用 vtable 中的 API 函数。这是通过一个可变参数的 temple 完成的,以使用任意数量的参数包装 API 函数。 我发现,只有当作为参数传递的数字被强制为长时,某些调用才有效:
vtablecall(pIntf, methodnumber, TRUE, 0, 0); //CRASHES
vtablecall(pIntf, methodnumber, (long long)TRUE, (long long)0, (long long)0); //WORKS
问题在于编译器本身不会强制执行(long long)。调试显示 TRUE 或 0 参数被视为 int。然后,也许它们在被发送到指向函数之前以某种方式被编译器(我怀疑)进行了优化。
我的目标是:模板中使用什么语法,以便将所有整数参数提升为长整型(如果可能的话,所有实数都提升为双精度)? 每次都放(long long)不是一个好的解决方案,因为有出错的风险,initializer_list也不是一个选项,因为某些参数可能是实数。
谢谢!
template <typename... pack> HRESULT WINAPI vtablecall(IUnknown* pIntf, const int methodnumber, pack... args){
HRESULT WINAPI (*psub)(IUnknown*, pack...)=(HRESULT WINAPI (*)(IUnknown*, pack...))((LPVOID**)pIntf)[0][methodnumber];
//// breakpoint here
return psub(pIntf, std::forward<pack>(args)...);
}
int main() {
IUnknown* pIntf=...
int mymethodnumber=43;
vtablecall(pIntf, mymethodnumber, pIntf, methodnumber, TRUE, 0, 0);
}
---> 崩溃:进程已退出,状态 = 0x80131506
调用“psub”之前调试器中的帧变量:
(IUnknown *) pIntf = 0x00000272be28ffa0
(const int) methodnumber = 43
(int) args = 1
(int) args = 0
(int) args = 0
(HRESULT (*)(IUnknown *, int, int, int)) psub = 0x000002aee04146ba
现在,将参数显式设置为 long long:
int main() {
IUnknown* pIntf=...
int mymethodnumber=43;
vtablecall(pIntf, mymethodnumber, pIntf, methodnumber, (long long)TRUE, (long long)0, (long long)0);
}
--->工作正常
调用“psub”之前调试器中的帧变量:
(IUnknown *) pIntf = 0x0000024bd525ffa0
(const int) methodnumber = 43
(long long) args = 1
(long long) args = 0
(long long) args = 0
(HRESULT (*)(IUnknown *, long long, long long, long long)) psub = 0x0000024bd57e46ba
答:
0赞
guard3
11/3/2023
#1
您可以使用它来定义自己的类型std::conditional
template<typename T>
using my_type_t = std::conditional_t<std::is_integral_v<T>, long long, T>;
如果是任何类型的整数,则为 ,否则为 。T
my_type_t<T>
long long
T
所以你可以这样使用它
...
HRESULT WINAPI (*psub)(IUnknown*, my_type_t<pack>...) = ...
评论