一、问题引入
有如下一段代码:
1 auto MakeGuard(HINTERNET hinternet) 2 { 3 if(!hinternet) { 4 const DWORD ec = ::GetLastError(); 5 throw std::system_error(ec, std::system_category(), "HINTERNET object creation failed."); 6 } 7 return std::unique_ptr<std::remove_pointer_t<HINTERNET>, decltype(&WinHttpCloseHandle)>(hinternet, WinHttpCloseHandle); 8 }
该函数的作用是将HINTERNET对象放到智能指针对象中并自定义删除该对象的删除器(仿函数,函数对象等),其中std::remove_pointer_t<HINTERNET>起到什么作用呢?
二、std::remove_pointer
该函数是一个模板函数,移除T类型的指针类型,如果T类型不是指针,那么去除的类型与T类型相同。例如:
std::remove_pointer<int>::type() ==> int std::remove_pointer<int*>::type() ==> int std::remove_pointer<int**>::type() ==> int* std::remove_pointer<const int*>::type ==>int std::remove_pointer<int* const>::type ==>int
cppreference 对remove_pointer_t 定义 : using remove_pointer_t = typename remove_pointer<T>::type,所以为了代码简洁,上面例子也可写成如下:
std::remove_pointer_t<int> ==> int std::remove_pointer_t<int*> ==> int std::remove_pointer_t<int**> ==> int* std::remove_pointer_t<const int*> ==>int std::remove_pointer_t<int* const> ==>int
所以,最上面的那一段代码中 std::unique_ptr<std::remove_pointer_t<HINTERNET>, decltype(&WinHttpCloseHandle)>(hinternet, WinHttpCloseHandle); 其实就是创建unique_ptr<T, Deleter>智能指针对象的构造函数。例如:
int* pValue = &value;
std::unique_ptr<std::remove_pointer_t<int*>(), decltype<&f>>(pValue, f); ==> std::unique_ptr<int, decltype<&f>>(value, f);
三、测试验证
std::remove_pointer的使用验证代码如下:
1 int value = 10; 2 auto removeValue1 = std::remove_pointer<decltype(value)>::type(); 3 std::cout << "removeValue1 type : " << typeid(removeValue1).name() << " "; 4 int* pValue = &value; 5 auto remoteValue2 = std::remove_pointer<decltype(pValue)>::type(); 6 std::cout << "removeValue2 type : " << typeid(remoteValue2).name() << " "; 7 int** ppValue = &pValue; 8 auto remoteValue3 = std::remove_pointer<decltype(ppValue)>::type(); 9 std::cout << "removeValue3 type : " << typeid(remoteValue3).name() << " "; 10 const int* pcValue = pValue; 11 auto remoteValue4 = std::remove_pointer<const int*>::type(); 12 std::cout << "removeValue4 type : " << typeid(remoteValue4).name() << " "; 13 int* const cpValue = pValue; 14 auto remoteValue5 = std::remove_pointer<int* const>::type(); 15 std::cout << "removeValue4 type : " << typeid(remoteValue5).name() << " ";
std::unique_ptr<std::remove_pointer_t<HINTERNET>, decltype(&WinHttpCloseHandle)>(hinternet, WinHttpCloseHandle)验证
1 void Close(int* param) 2 { 3 std::cout << "Close function. " << typeid(param).name() << "param " << param << " "; 4 } 5 6 auto MakeGuard(int* h) 7 { 8 return std::unique_ptr<std::remove_pointer_t<decltype(h)>, decltype(&Close)>(h, Close); // return std::unique_ptr<int, deleter>(); 9 }
1 int value = 10; 2 int* pValue = &value; 3 4 auto h = MakeGuard(pValue);
上面就是对std::remove_pointer模板函数的介绍,细心的同学可能会注意到MakeGurad函数还涉及到auto和decltype关键字的使用,后面会进行相关介绍。