在下面的代码中,编译器抱怨不明确。为什么?显然我正在传递非 const non & 对象。
\n#include <stdio.h>\n#include <ranges>\n#include <vector>\n#include <string>\n#include <iostream>\n\nusing namespace std;\ntemplate<class T>\nstring toStr(const T& obj)\n{\n return obj.toStr();\n}\n\ntemplate<class T>\nstring toStr(T val)\n{\n return std::to_string(val);\n}\nstruct A\n{\n string toStr(){return "A";} \n};\nint main()\n{\n A a;\n\n cout << toStr(static_cast<const A&>(a)) << '\\n';\n\n return 0;\n}\n\nRun Code Online (Sandbox Code Playgroud)\n我尝试在不同的编译器上编译它。效果是相同的。\n我什至尝试将其转换为所需的 const & 类型。没有。
\ncout << toStr(static_cast<const A&>(a)) << '\\n';\nRun Code Online (Sandbox Code Playgroud)\n编辑:
\n> main.cpp: In function \xe2\x80\x98int main()\xe2\x80\x99: main.cpp:35:18: error: call of\n> overloaded \xe2\x80\x98toStr(const A&)\xe2\x80\x99 is ambiguous 35 | cout <<\n> toStr(static_cast<const A&>(a)) << '\\n';\n> | ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~ main.cpp:17:8: note: candidate: \xe2\x80\x98std::string toStr(const T&) [with T = A; std::string\n> = std::__cxx11::basic_string]\xe2\x80\x99 17 | string toStr(const T& obj)\n> | ^~~~~ main.cpp:23:8: note: candidate: \xe2\x80\x98std::string toStr(T) [with T = A; std::string = std::__cxx11::basic_string]\xe2\x80\x99 23\n> | string toStr(T val)\n> | ^~~~~\nRun Code Online (Sandbox Code Playgroud)\n真正令人沮丧的是错误消息中的这一行:\nerror: call of
\n\n\n重载的 \xe2\x80\x98toStr(const A&)\xe2\x80\x99 是不明确的\n如果恰好有一个具有这样签名的函数,那么 this^^^ 怎么会是不明确的呢?
\n
在
cout << toStr(a) << '\n';
Run Code Online (Sandbox Code Playgroud)
您将类型的左值传递A给toStr()。
现在可以将其转换为const A&匹配的
const T& obj
Run Code Online (Sandbox Code Playgroud)
或将其复制到A匹配的
T val
Run Code Online (Sandbox Code Playgroud)
没有一个比另一个更专业,因此存在歧义。
请注意,A::toStr()应该有const资格在版本中使用string toStr(const T& obj)。
然后,您可以添加一些约束来选择正确的重载,例如检查类型是否具有toStr成员函数:
template <class, class = void>
struct has_toStr : std::false_type {};
template <class T>
struct has_toStr<T, std::void_t<decltype(std::declval<T&>().toStr())> >
: std::true_type {};
template <class T>
inline constexpr bool has_toStr_v = has_toStr<T>::value;
template <class T>
std::string toStr(const T& obj)
requires has_toStr_v<T>
{
return obj.toStr();
}
template <class T>
std::string toStr(T val)
requires(not has_toStr_v<T>)
{
return std::to_string(val);
}
Run Code Online (Sandbox Code Playgroud)