C - 编译器如何以参数为参数的过载函数在超载函数之间决定



在研究C 时,我遇到了复杂的转换序列主题,并且我遇到了一个无法独自解决的问题。

void g(const double)
{
    std::cout << "void g(const double)" << std::endl;
}
void g(const double&&)
{
    std::cout << "void g(const double&&)" << std::endl;
}
int main(int argc, char **argv)
{
    g(3.14);    
    return (0);
}
态------------
void g(const double)
{
    std::cout << "void g(const double)" << std::endl;
}
void g(const double&)
{
    std::cout << "void g(const double&)" << std::endl;
}
int main(int argc, char **argv)
{
    g(3.14);    
    return (0);
}

在这两个示例中,编译器抱怨过载函数" G(double)"的呼叫是模棱两可的事实。

void g(const double&&)
{
    std::cout << "void g(const double&&)" << std::endl;
}
void g(const double&)
{
    std::cout << "void g(const double&)" << std::endl;
}
int main(int argc, char **argv)
{
    g(3.14);    
    return (0);
}

但是在此示例中,程序正确编译并打印出" void g(const double&amp;&amp;)"。因此,我不明白为什么编译器抱怨前两个示例,但没有第三个示例。

超载分辨率表

此表总结了谁可以去哪里:

    ---------------------------------------------------------------------------------
               Caller    |   lvalue     | const lvalue |   rvalue     | const rvalue 
         Function        |              |              |              |  
    ---------------------------------------------------------------------------------
    [a]  f(X& x)         |    V (1)     |              |              |
    ---------------------------------------------------------------------------------
    [b]  f(const X& x)   |    V (2)     |      V       |    V (3)     |    V (2)
    ---------------------------------------------------------------------------------
    [c]  f(X&& x)        |              |              |    V (1)     |
    ---------------------------------------------------------------------------------
    [d]  f(const X&& x)  |              |              |    V (2)     |    V (1)
    ---------------------------------------------------------------------------------
  • 上述所有签名都可以一起生活。
  • V 标志标记可能有效的分辨率
  • 当相同的呼叫者有多个有效分辨率时,(1)比(2)等更好匹配
  • 除非有其他差异,例如方法等等,否则与上述任何一个差异都没有任何意义。添加字节版本:f(x x)与上述任何组合都无法正常工作 - 在大多数情况下,对于任何调用,都会产生歧义性,在某些情况下,它只会更喜欢Byval版本(如果仅与[a]生存 - 除了lvalue以外的任何调用都会更喜欢Byvalue版本,并且LVALUE调用将带有歧义)。
  • 签名[D]很少使用,请参阅:rvalue引用对const有任何用途吗?

在过载分辨率中,直接引用绑定是 sendentity conversion (即使添加了预选赛);double匹配double或参考到double的参数不是更好或更糟的。

在您的示例中,const在某种程度上有点红鲱鱼。对于非参考类型,f(const double),顶级const不是函数签名的一部分;在f(const double&)中,它仍然是直接的绑定,因此仍然是身份转换。

因此,您的前2个情况都是在两种情况下既是身份转换,又不偏爱一个或另一个情况。

在情况3中,规则C 14 [over.ics.rank]/3.1.3适用:

标准转换序列S1比标准转换序列更好 S2如果

  • [...]
  • s1和s2是参考绑定(8.5.3),两者都不是指一个隐式对象参数 无静态成员函数在没有参考值的情况下声明,S1与RVALUE参考结合了RVALUE,S2结合了LVALUE参考。

此规则允许对同一类型的RVALUE和LVALUE的功能过载。

最新更新