假设我有一个适用于原始指针的模板:
template<typename T>
void processPointer(T* ptr);
我不希望用void*
指针调用它。看来我有两个选择。我可以删除非模板重载:
void processPointer(void*) = delete;
或者我可以删除模板实例化:
template<>
void processPointer<void>(void*) = delete;
声明非模板重载更容易(没有尖角支架)。是否有理由我更愿意删除模板实例化?
答案 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;