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

时间:2011-11-02 13:05:32

标签: c++ g++

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

第二个库依赖于第一个库,它将枚举值传递给std :: cout(std :: ostringstream表现相同)并获取相应的数值而不是文本。不涉及模板化代码,因此它不是模板vs过载问题。我查看了预处理器输出,以验证正确的定义是否可见。我正在使用g ++ 4.1.2。

我无法在我的库之外重现问题(数千行),所以我无法发布任何示例代码。我尝试生成示例代码也让我相信我理解这应该如何工作。我猜测其中一个标题中包含的内容会导致编译器在选择哪个运算符时显示不同的选项<<使用。

我的问题:如何深入了解编译器在选择使用哪个版本的运算符以及选择标准版本的原因时选择的选择。

修改:根据要求添加签名: 请注意,这个简化示例没有出现问题。

第一个图书馆的标题:

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;

3 个答案:

答案 0 :(得分:5)

问题是,其中一条评论提到了Argument Dependent Lookup问题。当编译器执行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) {...}
}

这应该使ADL能够选择你过载。

答案 1 :(得分:2)

我建议您升级到至少g ++ 4.4以获得一些strongly-typed enumeration functionality

我最近升级到4.6并将我的所有枚举更改为枚举类 - 我相信强类型会让您了解代码中的错误。

答案 2 :(得分:1)

您是否尝试将论据明确地转换为<<