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&;&;)"。
所以我不明白为什么编译器会抱怨前两个示例,而不会抱怨第三个示例。
解决方案
重载解析表
此表汇总了哪些人可以去哪里:
---------------------------------------------------------------------------------
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)更匹配,依此类推。
- 使用上述任何一项重载val版本都没有意义,除非在方法上有其他差异,如const等。 添加BYVALE版本:F(X X)不能很好地与以上任何组合一起使用-在大多数情况下,它会导致任何调用的模糊性,对于某些情况,它只会更喜欢BYVAL版本(如果它只与[a]一起存在-除lvalue之外的任何调用都将首选BYVALE版本,而lvalue调用将导致歧义)。
- 签名[d]很少使用,请参阅:Do rvalue references to const have any use?
相关文章