C++ 模板参数推导相关问题
写项目的时候遇到相关问题, 上面注释的代码是编译不了的。
函数原型
WINBASEAPI
HANDLE
WINAPI
CreateFileA(
_In_ LPCSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
);
如果不加类型强制转换的话,也就是注释的代码 自动推导的类型如下
void * __ptr64 char [9]
unsigned long
int
int
int
int
int
很显然与函数原型不匹配。 下面是正确的推导。
void * __ptr64 char [9]
unsigned long
unsigned long
struct _SECURITY_ATTRIBUTES * __ptr64
unsigned long
unsigned long
void * __ptr64
好像不加强转是不行的
完整代码
#include <iostream>
#include <windows.h>
using namespace std;
template <typename Ret, typename... Args>
static inline auto spoof_call(
const void* trampoline,
Ret(*fn)(Args...), // 提供一个已有函数原型推导参数类型Args和返回类型Ret
Args... args)
-> Ret {
cout << typeid(Ret).name() << " ";
Ret r = 0;
return r;
}
// 打印出参数包中参数被自动推导的类型
template<typename Arg>
void print_param_packedtype(const Arg& arg){
//std::cout<<arg<<std::endl;
cout << typeid(Arg).name() << " ";
}
template<typename Arg,typename ...Args>
void print_param_packedtype(const Arg& arg,const Args& ...args){
//std::cout<<arg<<" ";
cout << typeid(Arg).name() << endl;
print_param_packedtype(args...); //递归解包
}
//
int main() {
spoof_call(nullptr, &CreateFileA, "test.txt", (GENERIC_READ | GENERIC_WRITE),
(DWORD)(FILE_SHARE_WRITE | FILE_SHARE_READ),
(LPSECURITY_ATTRIBUTES)NULL, (DWORD)CREATE_ALWAYS,
(DWORD)FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL);
print_param_packedtype("test.txt", (GENERIC_READ | GENERIC_WRITE),
(FILE_SHARE_WRITE | FILE_SHARE_READ),
NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
return 0;
}
但是他娘的模板参数推导是可以隐式转换的。
#include <iostream>
#include <windows.h>
using namespace std;
template<typename _T = float>
void test(_T p1) {
cout << p1 << " ";
}
template<typename _T = DWORD>
void test2(_T p1) {
cout << p1 << " ";
}
template<typename _T = HANDLE>
void test3(_T p1) {
cout << p1 << " ";
}
int main() {
test(4.0);// double 隐式转float
test2(1);// int隐式转DWORD
test3(0);// int转void*
return 0;
}
#include <iostream>
#include <windows.h>
using namespace std;
template <typename Ret, typename... Args>
void test(Ret(*fn)(Args...),Ret k) {// Ret类型不能由隐式转换了,原因不知道,反正编译器这样设计
cout << typeid(Ret).name();
cout << endl;
cout << typeid(k).name();
}
int main() {
//test(&CreateFileA,0); //error
test(&CreateFileA,(HANDLE)0);
return 0;
}