【问题标题】:Ambiguity not picked up by compiler编译器没有发现歧义
【发布时间】:2012-11-13 07:48:18
【问题描述】:

我不得不花费一些时间来查找和修复我在以下代码中设法隔离的错误:

#include <iostream>

struct A
{
    std::string S;
    A(const std::string s) { S = s; }
};

void f1(A a) { std::cout << "f1:a.S = " << a.S << "\n"; }
void f1(const std::string s) { std::cout << "f1:s = " << s << "\n"; }

void f2(A a) { std::cout << "f2:a.S = " << a.S << "\n"; }

int main()
{
    f1(A("test"));
    f1(std::string("test"));

    f2(A("test"));
    f2(std::string("test"));

    return 0;
}

这个错误是由f1-function:f2创建的被忽略的(由我和编译器(?))引起的,清楚地表明f1(A)f1(std::string)都适用于A,但是编译时编译器不会识别歧义,执行时输出是:

f1:a.S = test
f1:s = test
f2:a.S = test
f2:a.S = test

这种行为正确吗?编译器问题?还是只是普通的旧 PIBCAK?

【问题讨论】:

  • @Mat:是的,当我打电话给f1(std::string) 期待A 却没有得到它时,就会出现问题:(

标签: c++ ambiguity


【解决方案1】:

您描述的行为是预期的:没有歧义。当两个重载匹配得一样好并且都是“最佳重载”时,就会出现重载解析歧义。

当您使用A 类型的参数调用f1 时,第一个f1 是完全匹配的;第二个f1 根本不匹配。因此,f1 显然在重载解决方案中获胜。

当您使用std::string 类型的参数调用f1 时,第一个f1 通过A 的转换构造函数匹配;第二个f1 是完全匹配的。第二个f1 是更好的匹配:它是完全匹配的,不需要转换。这两个重载的匹配并不相同,因此没有歧义。第二个f1 在重载解析期间获胜。

【讨论】:

  • “完全匹配,不需要转换”:完全匹配,是的,但需要进行(标准)转换,在这种情况下是限定转换。
  • @ipc:不需要资格转换。顶级 cv 限定符不是函数类型的一部分,因此对重载决议没有影响。
  • @slashmais:重载分辨率充满了微妙之处。
  • 函数参数的 cv 限定不属于其签名的事实是因为它们与调用者无关。参数只是在调用期间初始化的局部变量,并且仅在正文中可用。因此,永远不应该将const-qualification 应用于函数声明中的参数,仅适用于定义 - 因为这意味着您可以更改后者中的参数是否为const,而不必更新前者以匹配,迫使您用户重新编译。 (这在 ABI 方面没有区别,但 make et al. 不要考虑到这一点)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-25
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
相关资源
最近更新 更多