0x5*_*9df 4 c++ templates pointers specialization delete-operator
下面的代码(编译和执行得当,做我想要的)是一个怪胎,而写一个类来存储需要删除的指针,当它不再知道自己的类型的能力不同类型的属性,我经历的一个小例子.我的解决方案是使用模板化函数创建一个Deleter类,该函数可以获取并存储其地址以删除特定类型.我不明白为什么这段代码有效,具体来说:
码:
#include <iostream>
#include <string>
#include <cassert>
#include <locale> //Just here as an unused class to specialize
using namespace std;
typedef void(*void_voidptr_func_t)(void*);
class ClassWithDestructor {
public:
~ClassWithDestructor() {
cout << "Destroyed\n";
}
};
class Deleter {
public:
template <class T>
static void Delete (T* ptr) {
assert(0);
}
//locale here can be any class
//it doesn't matter what class it is
//but if this specialization doesn't exist
//compile fails
template <class locale>
static void Delete(void* ptr) {
delete (locale*)ptr;
}
};
void* void_ptr_to_T = NULL;
void_voidptr_func_t T_delete_function = NULL;
template<class T>
void A() {
T* t = new T;
void_ptr_to_T = (void*)t;
T_delete_function = &Deleter::Delete<T>;
}
int main(int argc, char** argv) {
A<ClassWithDestructor>();
T_delete_function(void_ptr_to_T);
}
Run Code Online (Sandbox Code Playgroud)
编译器:MSVC++ 2010,Microsoft Extensions已禁用
输出:
摧毁
这个
template <class locale>
static void Delete(void* ptr) {
delete (locale*)ptr;
}
Run Code Online (Sandbox Code Playgroud)
不是专业化.这是一个过载.专业化将是这样的
template <>
static void Delete(locale* ptr) {
delete (locale*)ptr;
}
Run Code Online (Sandbox Code Playgroud)
所以实际上它等同于写作
template <class T>
static void Delete(void* ptr) {
delete (T*)ptr;
}
Run Code Online (Sandbox Code Playgroud)
实际上,您提出的行为是因为线路上的重载分辨率
T_delete_function = &Deleter::Delete<T>;
Run Code Online (Sandbox Code Playgroud)
第二个重载更具体,因为它接受void*而不是,T*并且无论如何都明确指定了类型.因此,在提到的超载的情况下,它选择它并且它编译并运行得很好.如果没有这种更具体的重载,编译器会调用另一个适当的,但更通用的一个触发断言.
您可以仔细检查,即删除#include <locale>行:编译器不会抱怨class locale未申报.