编译时必须存在无关的专业化?

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已禁用

输出:

摧毁

unk*_*ulu 5

这个

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未申报.