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

Joh*_*don 3 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)
{...}
Run Code Online (Sandbox Code Playgroud)

第二个图书馆的代码

std::cout << "Gain Text: " << hdr::AGC_GAIN_MODE << std::endl;
Run Code Online (Sandbox Code Playgroud)

Dav*_*eas 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) {...}
}
Run Code Online (Sandbox Code Playgroud)

这应该使ADL能够选择过载.