C++隐式转换引发operator=重载歧义的编译失败问题
重载歧义错误:std::string与自定义类V的赋值冲突
问题代码
#include <string> #include <boost/any.hpp> class V { public: V& operator=(int i) { v = i; return *this; } V& operator=(const std::string& s) { v = s; return *this; } operator int() const { return boost::any_cast<int>(v); } operator std::string() const { return boost::any_cast<std::string>(v); } private: boost::any v; }; int main() { V v; std::string s1 = "hello", s2; v = s1; s2 = v; }
编译错误信息
$ g++ test__boost_any.cpp test__boost_any.cpp: In function ‘int main()’: test__boost_any.cpp:37:9: error: ambiguous overload for ‘operator=’ (operand types are ‘std::__cxx11::string’ {aka ‘std::__cxx11::basic_string<char>’} and ‘V’) s2 = v; ^ In file included from /usr/include/c++/8/string:52, from test__boost_any.cpp:1: /usr/include/c++/8/bits/basic_string.h:668:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ operator=(const basic_string& __str) ^~~~~~~~ /usr/include/c++/8/bits/basic_string.h:718:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(_CharT) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ operator=(_CharT __c) ^~~~~~~~ /usr/include/c++/8/bits/basic_string.h:736:7: note: candidate: ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>& std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::operator=(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ operator=(basic_string&& __str) ^~~~~~~~
问题原因
V类同时提供了int和std::string类型的隐式转换运算符。执行s2 = v时,编译器存在两条可行的隐式转换路径:
- 将
v隐式转换为std::string,匹配std::string::operator=(const std::string&) - 将
v隐式转换为int,再转换为char(标准内置转换),匹配std::string::operator=(char)
这两条路径的转换优先级相同,编译器无法确定调用目标,因此触发重载歧义错误。
解决方案
方案1:使用显式转换运算符(C++11及以上)
将V类的转换运算符声明为explicit,禁用隐式转换,赋值时显式指定转换类型:
class V { public: // 保留原有赋值运算符不变 V& operator=(int i) { v = i; return *this; } V& operator=(const std::string& s) { v = s; return *this; } // 转换运算符改为explicit explicit operator int() const { return boost::any_cast<int>(v); } explicit operator std::string() const { return boost::any_cast<std::string>(v); } private: boost::any v; }; // main函数中修改赋值语句 int main() { V v; std::string s1 = "hello", s2; v = s1; s2 = static_cast<std::string>(v); // 显式转换 }
方案2:添加显式取值方法替代隐式转换
移除类V的转换运算符,改为提供明确的取值成员函数:
class V { public: V& operator=(int i) { v = i; return *this; } V& operator=(const std::string& s) { v = s; return *this; } int asInt() const { return boost::any_cast<int>(v); } std::string asString() const { return boost::any_cast<std::string>(v); } private: boost::any v; }; // main函数中调用取值方法 int main() { V v; std::string s1 = "hello", s2; v = s1; s2 = v.asString(); }
内容的提问来源于stack exchange,提问作者user180574
相关产品推荐
相关产品推荐

