在重载决策algorithm中如何确定模糊度?
我想了解重载parsing方法。
为什么这是模棱两可的:
void func(double, int, int, double) {} void func(int, double, double, double) {} void main() { func(1, 2, 3, 4); }
但这不是?
void func(int, int, int, double) {} void func(int, double, double, double) {} void main() { func(1, 2, 3, 4); }
在第一种情况下,有2个确切的参数匹配和2个转换对1个完全匹配和3个转换,第二个情况下,有3个完全匹配和1个转换对1个完全匹配和3个转换。
那么为什么一个模棱两可,一个不是? 这里的逻辑是什么?
重载parsing规则只在所有匹配的集合上定义了部分顺序 – 如果过载F1
不比F2
更好匹配,则并不意味着F2
比F1
更好匹配。 精确的部分顺序可以被认为是比较k
维中的两个点,其中参数的数量是k
。 (x_1, x_2,..., x_k) < (y_1, y_2,..., y_k) if x_i <= y_i for all i and x_j < y_j for at least one j
。 这正是标准定义的候选非模板函数的部分顺序。
让我们看看你的例子:
void func(double, int, int, double) {} vvv vvv vvv better better equal void func(int, double, double, double) {} vvv vvv better equal
所以超负荷都不会比其他的好。
在你的第二个例子中:
void func(int, int, int, double) {} vvv vvv vvv vvv equal better better equal void func(int, double, double, double) {} vvv equal
现在,第一个超载比第二个好,但是一个参数并不比第二个更差。 因此,没有歧义 – 部分顺序确实宣布第一个更好。
(上面的描述没有考虑函数模板,你可以在cppreference中find更多的细节。)
标准(§[over.match.best] / 1)的措词是:
让ICS i (F)表示将列表中的第i个参数转换为可行函数F的第i个参数的types的隐式转换序列。
如果对于所有参数i ,ICS i (F1)不是比ICS i (F2)更差的转换序列,则可行函数F1被定义为比另一可行函数F2更好的函数,然后
– 对于一些参数j ,ICS j (F1)是比ICS j (F2)更好的转换序列,
在你的第一个例子中,这两个函数在第一个testing中失败了。 对于第一个参数,第一个函数(采用double
)具有比第二个函数更糟的转换顺序。 对于第二个参数,第二个函数的转换顺序比第一个要差(再次, int
必须在一种情况下被提升为double
,而另一个则不能)。
因此,这两个函数都没有通过第一个规则,而且调用是不明确的。
在第二对函数之间,第一个函数的每个参数都至less和第二个函数的匹配参数一样好。 然后我们继续第二条规则,发现至less有一个论点(事实上是两个),第一个函数比第二个函数具有更好的转换(身份而不是升级)。
因此,第一个function是更好的匹配,并将被选中。
歧义由排名决定:
- 完全匹配:不需要转换,左值到右值转换,资格转换,用户定义的类types到同一类的转换
- 推广:整体推广,浮点推广
- 转换:积分转换,浮点转换,浮点积分转换,指针转换,指针到成员转换,布尔转换,派生类到用户定义的转换
完全匹配胜vs胜利vs转换。
在这个例子中:
void func(int, bool, float, int){cout << "int,bool,float,int" << endl;} void func(int, bool, int, int){cout << "int,int,int,int" << endl;} int main() { func(1,1,3.4,4); }
参数1( 1
)在两者上完全匹配
参数2( 1
)在两者上完全匹配
参数3( 3.4
)可以转换为float和int – 不确定性也不好 。
参数4( 4
)是两者完全匹配的
但是,如果我们这样做: func(1,1,3.4f,4);
( 3.4f
)现在完全匹配!
void func(int, bool, float, int)
然后赢得战斗。