【问题标题】:Why is g++ saying 'no match for ‘operator=’ when there clearly is, and Visual Studio can see that there is?为什么 g++ 说 'operator=' 不匹配,而 Visual Studio 可以看到有?
【发布时间】:2010-12-29 05:04:20
【问题描述】:

我正在编写一个接口库,它允许访问regula::State 类型对象中的表中的变量(理论上可以达到无限深度)。我通过在一个类中重载operator[] 来实现这一点,然后返回同一个类的另一个,并根据需要再次调用operator[]。例如:

regula::State t;
t["math"]["pi"] = 3.14159;

上面应该将值3.14159 放在表math 中的变量pi 中。基本上,它通过让t 返回一个代表math 的代理对象来实现这一点,它返回另一个代表pi 的代理对象,我们实际上将变量保存到其中。 this 的内部与问题无关,但这里是函数头。

LObject LObject::operator[] (const std::string name);

基本上,在上面的例子中,程序应该用字符串"math"调用toperator[]并返回另一个对象,然后用字符串"pi"调用该对象的operator[],返回最后一个对象,然后使用 operator= 将值分配给那个对象。

template <typename T>
T LObject::operator= (const T& value);

返回的T 只是传递的value 的副本。

现在,我的代码在 Visual C++ 2008 中没有产生任何错误,并且运行良好。但是当我尝试在 Linux 上使用 g++ 编译它时,我收到以下错误:

../../test/regula-test.cpp:100: error: no match for ‘operator=’ in 
‘L.regula::State::operator[](std::basic_string<char, std::char_traits<char>, 
std::allocator<char> >(((const char*)"Numbers"), ((const std::allocator<char>&)((const 
std::allocator<char>*)(& std::allocator<char>()))))) = Numbers’
../../include/regula.hpp:855: note: candidates are: regula::LObject&
 regula::LObject::operator=(const regula::LObject&)

出于某种原因,g++ 似乎试图在 operator[] 上调用 operator=,而不是像应有的那样在返回的对象上调用。

我实际上可以通过将operator= 上的返回类型替换为void 来修复此错误:

template <typename T>
/*T*/ void LObject::operator= (const T& value);

但这并不可取,此外,我在其他几个位置也有类似的错误,operator== 类似重载:

../../test/regula-test.cpp:153: error: no match for ‘operator==’ in ‘pi == 
L.regula::State::operator[](std::basic_string<char, std::char_traits<char>, 
std::allocator<char> >(((const char*)"pi"), ((const std::allocator<char>&)((const 
std::allocator<char>*)(& std::allocator<char>())))))’

我不明白为什么在 g++ 中会出现这个错误,或者为什么在 Visual C++ 中没有出现。任何人都可以对此有所了解或推荐任何解决方案吗?

【问题讨论】:

  • 发布真实代码。你的样品坏了。 regula::State t["math"]["pi"] = 3.14159; 不能是有效的 C++ 语句。你的operator = 的“固定”声明也被破坏了,因为现在那里没有T
  • @AndreyT:我很抱歉,该行不应该被截断。我已经修复了有问题的样本。
  • 你能把它归结为一个小sn-p来演示错误吗?
  • 那么,当您在 operator = 上使用 void 返回类型时,它会在 GCC 中编译和工作吗?
  • 这里没有什么明显的亮点。我们需要看到更多的实现来帮助你。但是根据经验和直觉,让我大胆猜测一下,您在模板代码的某处遗漏了 typename 消歧器。 MSVC 让您可以忽略它,而 gcc 经常发出非直观的错误消息。

标签: c++ operators g++ compiler-errors


【解决方案1】:

ISO 标准第 5.17 节说

有几个赋值运算符,它们都从右到左分组。都需要一个可修改的左值作为左操作数,赋值表达式的类型是左操作数的类型。赋值操作的结果是赋值后存储在左操作数中的值; 结果是一个左值

您的operator= 不仅返回错误的类型,甚至没有返回左值。假设 GCC 的错误消息不包括除 operator=(const regula::LObject&amp;) 之外的任何其他候选者,GCC 完全忽略了您的重载。它提到的operator= 是默认的、自动生成的函数。

乍一看,您的operator[] 也应该返回一个引用。正如所写,像您的示例这样的赋值表达式根本不应该工作。

所以,你应该有函数

LObject &LObject::operator[] (const std::string name);

template <typename T>
LObject &LObject::operator= (const T& value);

【讨论】:

  • 好吧,声明 operator = 的方式确实是错误的,但声明 operator [] 的方式不一定是错误的。事实上,::std::vector&lt;bool&gt; 的特化定义了 operator [] 以返回一个 _Bit_reference(不是真正的引用)。 _Bit_reference 又是一个定义自己的类_Bit_reference &amp;_Bit_reference::operator =(bool x)
  • 他的 operator[] 有效;据我所知,operator[] 根本不需要返回左值(现在不查找)。关键是,他使用它作为左值。
  • 嗯,::std::vector&lt;bool&gt;::operator [] 的结果也打算用作左值,它像他一样返回一个临时值。
  • LObject 有可能(但不太可能)是将修改传递给另一个对象的代理。我会坚持我的建议。
  • 我最终通过以下方式解决了我的问题:a.) 让 operator= 成为 void 函数,b.) 每当使用运算符时手动转换为适当的类型。不方便,但由于我写这篇文章基本上是为了解决我自己的痒,我决定我可以处理妥协。感谢您的所有意见。
猜你喜欢
  • 2014-04-25
  • 2019-03-18
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 2019-05-10
  • 2016-07-30
  • 2013-05-19
  • 1970-01-01
相关资源
最近更新 更多