编译器选择了错误的运算符<<

Compiler chooses the wrong operator<<

本文关键字:lt 运算符 选择 错误 编译器      更新时间:2023-10-16

我有两个库,一个依赖于另一个。第一个库定义了一些枚举,并提供了一个<<()操作符,用于为每个枚举打印一小段文本。我有单元测试证明这是有效的。

第二个库依赖于第一个库,将枚举值传递给std::cout (std::ostringstream的行为与之相同),并获得相应的数值而不是文本。没有模板化的代码,所以它不是模板与重载的问题。我已经检查了预处理器输出,以验证是否可以看到正确的定义。我使用的是g++ 4.1.2.

我无法在我的库(数千行)之外重现问题,所以我不能发布任何示例代码。我尝试生成示例代码也使我确信我理解这应该是如何工作的。我猜,其中一个头中包含的东西导致编译器在选择哪个操作符时做出不同的选择<<使用。

我的问题:我怎样才能了解编译器在选择使用哪个版本的操作符时有哪些选择,以及为什么它选择了标准版本而不是我的。

Edit:按要求添加签名:请注意,这个简化的示例并没有出现这个问题。

第一个库的头文件:

namespace utcp {
  enum GainType {AGC_GAIN_MODE, MAN_GAIN_MODE };
}
// I've tried this passing the argument by value as well.
inline std::ostream& operator<<(std::ostream &os, const hdr::GainType &val)
{...}

第二个库中的代码

std::cout << "Gain Text: " << hdr::AGC_GAIN_MODE << std::endl;

问题是,正如其中一条注释提到的一个参数依赖查找问题。当编译器执行查找std::cout << my_enum_variable时,它将查找当前命名空间、std命名空间和定义了my_enum_variable类型的命名空间。只有在没有候选项的情况下,它才会向上搜索封闭的名称空间。在这种情况下,由于任何enum都可以隐式地转换为int,因此它将应用该转换,而不会查看封闭的名称空间。using指令在这方面没有帮助。

简单的解决方案是将重载的operator<<移动到与枚举相同的名称空间中:

namespace utcp {
  enum GainType {AGC_GAIN_MODE, MAN_GAIN_MODE };
  inline std::ostream& operator<<(std::ostream &os, const GainType &val) {...}
}

我建议您至少升级到g++ 4.4以获得一些强类型枚举功能。

我最近升级到4.6,并将我所有的枚举更改为enum类-我相信强类型会给你一个关于代码中的错误的想法。

您是否尝试显式地将您的参数转换为<< ?