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

发布于 2024-12-13 09:59:05 字数 879 浏览 4 评论 0 原文

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

第二个库依赖于第一个库,将枚举值传递给 std::cout (std::ostringstream 的行为相同)并获取相应的数值而不是文本。不涉及模板化代码,因此这不是模板与重载问题。我查看了预处理器输出以验证正确的定义是否可见。我正在使用 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;

I have two libraries, one of which depends on the other. The first library defines some enumerations and provides an operator<<() that prints a short chunk of text for each enumeration. I have unit tests proving that this works.

The second library, which depends on the first, passes an enumeration value to std::cout (std::ostringstream behaves the same) and gets the corresponding numerical value rather than the text. No templated code is involved so it's not a template vs overload issue. I've looked through the preprocessor output to verify that the correct definitions are visible. I'm using g++ 4.1.2.

I'm unable to reproduce the problem outside of my libraries (which are thousands of lines), so I can't post any example code. My attempt to produce example code also convinces me that I understand how this is supposed to work. I'm guessing that something included in one of the headers is causing the compiler to make a different choice when selecting which operator<< to use.

My Question: How can I get insight into what choices the compiler has in choosing which version of the operator to use and why it picked the standard one over mine.

Edit: Adding signatures as requested:
Note though that this simplified example does not exhibit the problem.

Header from the first library:

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)
{...}

Code from the second libary

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

傲性难收 2024-12-20 09:59:05

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

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

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

这应该使 ADL 能够选择您的重载。

The problem is, as one of the comments mentions an Argument Dependent Lookup problem. When the compiler performs lookup for std::cout << my_enum_variable it will look in the current namespace, in the std namespace and the namespace where the type of my_enum_variable is defined. Only if there is no candidate, it will go up and search the enclosing namespaces. In this case, because any enum is implicitly convertible to int it will apply that conversion and not look in enclosing namespaces. The using directive does not help there.

The simple solution is moving the overloaded operator<< into the same namespace that the enumeration:

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

This should enable ADL to pick you overload.

酒绊 2024-12-20 09:59:05

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

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

I recommend that you upgrade to at least g++ 4.4 to get some strongly-typed enumeration functionality.

I recently upgraded to 4.6 and changed all my enums to enum class - I believe strong-typing will give you an idea as to the error in the code.

风蛊 2024-12-20 09:59:05

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

Did you try to explicitly cast your argument to << ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文