在下面的代码中,编译器会抱怨二义性。为什么?很明显我传递的是non const non & object。
#include <stdio.h>
#include <ranges>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
template<class T>
string toStr(const T& obj)
{
return obj.toStr();
}
template<class T>
string toStr(T val)
{
return std::to_string(val);
}
struct A
{
string toStr(){return "A";}
};
int main()
{
A a;
cout << toStr(static_cast<const A&>(a)) << '\n';
return 0;
}
我试着在不同的编译器上编译它。效果是一样的。我甚至试着把它转换成想要的const & type。不知道
cout << toStr(static_cast<const A&>(a)) << '\n';
编辑:
> main.cpp: In function ‘int main()’: main.cpp:35:18: error: call of
> overloaded ‘toStr(const A&)’ is ambiguous 35 | cout <<
> toStr(static_cast<const A&>(a)) << '\n';
> | ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~ main.cpp:17:8: note: candidate: ‘std::string toStr(const T&) [with T = A; std::string
> = std::__cxx11::basic_string]’ 17 | string toStr(const T& obj)
> | ^~~~~ main.cpp:23:8: note: candidate: ‘std::string toStr(T) [with T = A; std::string = std::__cxx11::basic_string]’ 23
> | string toStr(T val)
> | ^~~~~
真正令人沮丧的是来自error msg的这一行:错误:调用
重载的'toStr(const A&)'是不明确的如果只有一个函数具有这样的签名,那么这^怎么可能是不明确的呢?
3条答案
按热度按时间iqjalb3h1#
在
将
A
类型的左值传递给toStr()
。它现在可以将其转换为
const A&
以匹配或将其复制到
A
以进行匹配没有一个比另一个更专业,因此是模糊的。
请注意,
A::toStr()
应该是const
,才能在string toStr(const T& obj)
版本中使用。然后你可以添加一些约束来选择正确的重载,比如检查类型是否有
toStr
成员函数:7xzttuei2#
按引用和按值参数不能用于消除重载的歧义。(最多可以使用不同类型的引用,例如:
const T &
与T &&
,但在这里无关紧要。)这里的问题是函数不是SFINA友好的(即,函数体对于特定
T
无效不足以在重载解析期间拒绝该重载)。你需要明确地阐明这些条件,例如:使用
requires
:我还做了一些表面上的改变。您还必须
const
-限定A
的toStr()
。在C++20之前,它看起来像这样:
mnemlml83#
阅读完整的信息,而不仅仅是第一行:
toStr(const A&): candidate
与toStr(T val): candidate
有歧义。假设
toStr(a)
,你会如何选择?通过引用还是通过值传递?模棱两可。试图通过使用
static_cast<const A&>
来强制类型不会改变任何东西,通过引用或通过值传递?一般来说,不要重载带有pass-by-ref和匡威-value的函数,否则会导致歧义。