功能超载以NULLPTR作为参数分辨率

Function overload resolution with nullptr as argument

本文关键字:参数 分辨率 NULLPTR 超载 功能      更新时间:2023-10-16

考虑以下代码。尽管fun的两个过载都接受指针,但将nullptr传递给fun并不会导致任何汇编错误。而非常相似的功能bun无法编译。当我使用typeid(i).name() 打印参数i的类型时(修改代码后,只是为了打印此版本) 我获得相同的类型,只需int*即可。解决fun情况下歧义性但bun失败的规则是什么?预先感谢!

#include <iostream>
struct Foo {
    int sth;
};
template< class U>
void fun(decltype(U::sth)* i){
    std::cout << "1" << std::endl;
}
template< class U>
void fun(U* i){
    std::cout << "2" << std::endl;
}
void bun(decltype(Foo::sth)* i){
    std::cout << "3" << std::endl;
}
void bun(Foo* i){
    std::cout << "4" << std::endl;
}
int main ( )
{
    fun<Foo>(nullptr);
    // bun(nullptr); --> call of overloaded 'bun(std::nullptr_t)' is ambiguous        
    return 0;          
}
-----------------------
output : 1

好吧,实际上,GCC接受您的代码,但Clang不接受。因此,起初并不明显是否呼叫是模棱两可的。

您询问在fun情况下解决什么规则;海湾合作委员会显然认为有这样的规则。我认为GCC应用的规则是[over.match.best]/1.7的规则,它优先于更专业函数模板而不是较少专业的模板。

确定哪种功能模板比[temp.func.order]中描述的另一个功能模板更专业,并在此SO答案中彻底解释了。但是,您会注意到,当尝试将此过程应用于fun的两个过载时,我们会遇到一个问题,即需要在第一个过载中替换为U的唯一合成类型,需要有一个成员命名为sth,并且未指定该成员的性质,尽管对于人类来说,即使第二个fun过载中的扣除都必须成功,无论sth的类型是什么,但编译器可能无法证明这一点。

这是CWG1157。由于此问题仍然没有提议的解决方案,因此我对WG21是否打算成功解决此问题。