gpt4 book ai didi

c++ - 运算符重载决议如何在 namespace 内工作?

转载 作者:可可西里 更新时间:2023-11-01 15:53:45 27 4
gpt4 key购买 nike

我发现 C++ 运算符重载解析的奇怪行为,我自己无法解释。指向描述它的某些资源的指针与答案一样好。

我有 2 个翻译单元。在一个(称为 util.cpp/h)中,我声明并定义了两个运算符(我省略了可读性的实际实现,无论如何都会出现问题):

// util.h
#ifndef GUARD_UTIL
#define GUARD_UTIL

#include <iostream>

std::istream& operator>>(std::istream& is, const char* str);
std::istream& operator>>(std::istream& is, char* str);
#endif

和:

//util.cpp
#include "util.h"
#include <iostream>

std::istream& operator>>(std::istream& is, const char* str) {
return is;
}
std::istream& operator>>(std::istream& is, char* str) {
return is;
}

这些运算符当然在全局命名空间中,因为它们对标准类型和内置类型进行操作,并且应该可以在任何地方使用。它们在全局命名空间(例如从 main())或明确告诉编译器它们在全局命名空间中(参见代码示例)时都能正常工作。

在另一个翻译单元(称为 test.cpp/h)中,我在命名空间内使用这些运算符。这一直有效,直到我将类似的运算符放入此命名空间。添加此运算符后,编译器(例如 gcc 或 clang)将无法再找到可行的运算符>>。

// test.h
#ifndef GUARD_TEST
#define GUARD_TEST

#include <iostream>

namespace Namespace {
class SomeClass {
public:
void test(std::istream& is);
};

// without the following line everything compiles just fine
std::istream& operator>>(std::istream& is, SomeClass& obj) { return is; };
}

#endif

和:

//test.cpp
#include "test.h"
#include "util.h"
#include <iostream>

void Namespace::SomeClass::test(std::istream& is) {
::operator>>(is, "c"); //works
is >> "c" //fails
}

为什么编译器在命名空间中没有运算符>>时找到正确的运算符而在有运算符时却找不到?为什么运算符会影响编译器找到正确签名的能力,即使它具有不同的签名?

解决这个问题的一个尝试是把

std::istream& 运算符>>(std::istream& is, const char* str) {::operator>>(is, str);

进入命名空间,但链接器提示以前的定义。所以额外的:为什么链接器可以找到编译器找不到的东西?

最佳答案

这是一个名称隐藏问题。标准说 (c++03, 3.3.7/1)

A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class (10.2).

您案例上的“名称”为 operator>>和命名空间构成嵌套的声明区域。

解决这个问题的最简单方法是使用 using声明命名空间本地的声明 operator<< :

namespace your_namespece {
std::istream& operator>>(std::istream& is, SomeClass& obj) { return is; };
using ::operator>>;
}

请注意,此功能不会干扰 Koenig 查找(至少在您的情况下,原则上可以),因此来自 std:: 的 IO 运算符仍然会被发现。

PS:解决此问题的另一种可能性是为 SomeClass 定义运算符。作为inline friend .此类函数在 namespace 级别(在“它们的”类之外)声明,但从那里不可见。它们只能通过 Koenig 查找找到。

关于c++ - 运算符重载决议如何在 namespace 内工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11359562/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com