其他分享
首页 > 其他分享> > c – 为什么编译器在没有引用运算符的情况下无法决定调用哪个函数?

c – 为什么编译器在没有引用运算符的情况下无法决定调用哪个函数?

作者:互联网

下面你可以看到名为max的小函数.

template <typename T>
T max(T& arg1, T& arg2) {    
    if (arg1 > arg2) {
        return arg1;
    } else {
        return arg2;
    }
}

当我在main中调用此函数时,它完全有效,但是如果我从参数中删除引用

T max(T arg1, T arg2)  

然后编译器给出以下错误

main.cpp:18:21: error: call of overloaded 'max(int&, int&)' is ambiguous

很明显,编译器无法决定是调用我的函数还是标准函数.这里的问题是如何在论证的主题上有参考时如何决定和工作?

当我用恒定参数调用函数时

const int a = 12;
const int b = 24;
cout << max(a, b) << endl;

它调用标准的max函数.但是当我使用非const值调用时,它会调用我的函数.

我可以理解,如果对象是const,const函数将被调用,其他地方将调用非const函数.但为什么它应该引用触发这种机制?为什么没有参考运算符就无法决定呢?

解决方法:

这是一个关于重载解决的问题,没有人解决过.让我们暂时忽略模板,因为它们并不是严格相关的,让我们假装我们声明了这些重载:

void foo(int& );       // (1)
void foo(const int&);  // (2)

当我们尝试用左值调用foo时会发生什么?

int i;
foo(i);

两位候选人都可行.确定哪个是最佳可行候选者的第一个规则是转换序列,以及[over.ics.rank]:

Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence
S2 if
— […]
— S1 and S2 are reference bindings (8.5.3), and the types to which the references refer are the same
type except for top-level cv-qualifiers, and the type to which the reference initialized by S2 refers
is more cv-qualified than the type to which the reference initialized by S1 refers.

S1和S2都是引用绑定,引用引用的类型(int和const int)除了cv-qualifiers外是相同的,但S2的引用类型比S1更符合cv.最不合格的参考获胜.因此,(1)是优选的.

这正是您的功能模板的原因

template <typename T> T max(T&, T&); // (1)

优先于标准函数模板:

template <typename T> T const& max(T const&, T const&); // (2)

问题的第二部分介绍了这个额外的过载:

void foo(int& );       // (1)
void foo(const int&);  // (2)
void foo(int );        // (3)

我们知道(1)优于(2),但是不存在区分(1)和(3)的规则.没有“参考优于非参考”或反之亦然.因此,两个候选人都同样可行 – 这是不正确的.因此关于歧义的错误.这就是为什么:

template <typename T> T max(T, T); // (3)
template <Typename T> T const& max(T const&, T const&); // (2)

没为你编译.

标签:c,templates,overload-resolution
来源: https://codeday.me/bug/20190829/1762129.html