如果有专门的函数和模板函数,为什么没有必要专门针对 std::nullptr_t`
Why isn't it necessary to specialize for `std::nullptr_t` if there's a specialized function AND a templated function
考虑以下代码:
#include <iostream>
using namespace std;
void fun(const char* s){
if (s == nullptr) {
puts("const char* nullptr");
} else {
printf("%s\n", s);
}
}
template <typename T>
void fun(T* p){
printf("%p\n", p);
}
int main() {
int a;
fun("abc"); // Resolves to fun(const char*)
fun(&a); // Specializes the template to int*
fun(nullptr); // Uses fun(const char*)??
fun(NULL); // Same as above
}
令我惊讶的是 g++ 7.2.0
不会 抛出关于模糊重载解析的错误,因为我认为 nullptr
和 NULL
可以适合 任何 指针类型,包括从模板专门化的 fun(int*)
,前提是没有专门用于 std::nullptr_t
.
的重载
为什么 fun(nullptr)
和 fun(NULL)
直接解析为 fun(const char *)
?
std::nullptr_t
不是指针,因此它不会在您的函数模板中进行模式匹配 T*
。
与直觉相反,以下断言不会触发:
static_assert(std::is_pointer<std::nullptr_t>() == false);
至于NULL
,是一个实现定义的宏。如果要相信 cppreference,它要么是值为零的整数文字(因此不是指针),要么是 std::nullptr_t
类型的纯右值,这在上面已经解释过了。它是不是一个void*
指针。
考虑以下代码:
#include <iostream>
using namespace std;
void fun(const char* s){
if (s == nullptr) {
puts("const char* nullptr");
} else {
printf("%s\n", s);
}
}
template <typename T>
void fun(T* p){
printf("%p\n", p);
}
int main() {
int a;
fun("abc"); // Resolves to fun(const char*)
fun(&a); // Specializes the template to int*
fun(nullptr); // Uses fun(const char*)??
fun(NULL); // Same as above
}
令我惊讶的是 g++ 7.2.0
不会 抛出关于模糊重载解析的错误,因为我认为 nullptr
和 NULL
可以适合 任何 指针类型,包括从模板专门化的 fun(int*)
,前提是没有专门用于 std::nullptr_t
.
为什么 fun(nullptr)
和 fun(NULL)
直接解析为 fun(const char *)
?
std::nullptr_t
不是指针,因此它不会在您的函数模板中进行模式匹配 T*
。
与直觉相反,以下断言不会触发:
static_assert(std::is_pointer<std::nullptr_t>() == false);
至于NULL
,是一个实现定义的宏。如果要相信 cppreference,它要么是值为零的整数文字(因此不是指针),要么是 std::nullptr_t
类型的纯右值,这在上面已经解释过了。它是不是一个void*
指针。