何时删除模板实例化比删除非模板重载更好?

时间:2014-01-09 18:21:37

标签: c++ templates c++11 overloading

假设我有一个适用于原始指针的模板:

template<typename T>
void processPointer(T* ptr);

我不希望用void*指针调用它。看来我有两个选择。我可以删除非模板重载:

void processPointer(void*) = delete;

或者我可以删除模板实例化:

template<>
void processPointer<void>(void*) = delete;

声明非模板重载更容易(没有尖角支架)。是否有理由我更愿意删除模板实例化?

4 个答案:

答案 0 :(得分:19)

Here's one reason支持模板版本:processPointer<void>(void*)仍然可以直接调用,避免其他重载。

答案 1 :(得分:4)

我认为没有理由在这里进行模板化

事实上,通过删除非模板重载,您可能会摆脱一些我现在无法想到的边缘情况模糊调用,因为非模板优先于模板实例化。因此,在大多数情况下,可以按照需要进行工作。

答案 2 :(得分:4)

这可能会提供见解:

#include <iostream>

struct X
{
    template<typename T>
    void processPointer(T* ptr) {
        std::cout << "Template\n";
    }

    // error: explicit specialization in non-namespace scope ‘struct X’
    // template<>
    // void processPointer(void*) = delete;

    // Overload but no specialization
    // This will prevent lookup the specialization outside the class, when no
    // template argument is explicitly given.  However, with an explicit 
    // template argument the specialization is called.
    void processPointer(void*) = delete;
};

// Specialization outside the class body
template<>
void X::processPointer(void* ptr) {
    std::cout << "Specialization\n";
}

int main ()
{
    X x;
    //error: use of deleted function ‘void X::processPointer(void*)’
    //x.processPointer((void*)0);

    // Explicit template argument:
    x.processPointer<void>((void*)0);
}

结论:@Casey的答案成立。

答案 3 :(得分:0)

假设您要将pointer类型的参数void*(或简称为nullptr)传递给processPointer函数,并且您还想调用其类型{的特化{1}}。那你应该写

Type

processPointer(static_cast<Type>(pointer));

但是

void processPointer(void*) = delete;

你可以编写更短的代码:

template<>
void processPointer<void>(void*) = delete;

因此,两种变体都可以用于不同的情况。

然而,在某些情况下,具有非模板过载的变体的类似物可能是唯一的方法。 假设有一个带有两个参数的函数模板:

processPointer<Type>(pointer);

您不希望使用template<typename T, typename U> void processPointer(T* ptr1, U* ptr2); 指针作为第一个参数调用它。 C ++中不允许对函数模板进行部分特化,因此此代码不正确:

void*

你必须使用另一个:

template<typename U>
void processPointer<void, U>(void*, U*) = delete;