如何让func(0)调用size_t重载、func(NULL)调用int*重载解决歧义?
解决方案
要实现func(0)匹配size_t版本、func(NULL)匹配int*版本,可以通过重载决议优先级控制和SFINAE约束来实现,具体方案如下:
方法1:利用std::nullptr_t重载(C++11及以上)
C++11引入的std::nullptr_t是专门的空指针类型,我们可以为其添加专属重载,同时约束size_t版本仅接受算术类型:
#include <cstddef> #include <type_traits> template<class T> T func(int*) { return T(0); }; int* someptr; // 专门处理nullptr(包括定义为nullptr的NULL) template<class T> T func(std::nullptr_t) { return func<T>(static_cast<int*>(nullptr)); } // 仅接受算术类型,排除指针类型 template<class T, typename U, typename std::enable_if_t<std::is_arithmetic_v<U> && !std::is_pointer_v<U>, int> = 0> T func(U v) { return func<T>(someptr + static_cast<size_t>(v)); } int main() { func<float>(nullptr); // 调用int*版本(通过nullptr_t重载转发) func<float>(0); // 调用size_t版本(算术类型匹配) func<float>(NULL); // 若NULL定义为nullptr,则调用int*版本;若NULL为0,需额外处理 }
方法2:强制NULL为指针类型(兼容旧标准)
若编译器中NULL被定义为整数0,可以通过预处理强制NULL为int*类型,消除歧义:
#include <cstddef> #include <type_traits> // 强制NULL为int*类型 #ifdef NULL #undef NULL #define NULL static_cast<int*>(0) #endif template<class T> T func(int*) { return T(0); }; int* someptr; // 仅接受算术类型 template<class T, typename U, typename std::enable_if_t<std::is_arithmetic_v<U>, int> = 0> T func(U v) { return func<T>(someptr + static_cast<size_t>(v)); } int main() { func<float>(nullptr); // 调用int*版本 func<float>(0); // 调用size_t版本(int是算术类型) func<float>(NULL); // 调用int*版本(NULL是int*类型) }
原理说明
- SFINAE约束:通过
std::is_arithmetic_v确保size_t版本仅接受整数、浮点等算术类型,排除指针类型的匹配可能。 - 重载优先级:专属
std::nullptr_t模板重载比通用模板重载优先级更高,因此nullptr或强制为指针的NULL会优先匹配int*版本。 - 精确匹配优先:当传递
0(算术类型)时,会精确匹配约束为算术类型的size_t版本,避免与指针版本的转换歧义。
内容的提问来源于stack exchange,提问作者Apple_Banana
相关产品推荐
相关产品推荐

