C++ 在命名空间中找不到函数
Posted
技术标签:
【中文标题】C++ 在命名空间中找不到函数【英文标题】:C++ can't find function out of namespace 【发布时间】:2019-07-16 16:18:55 【问题描述】:编译以下代码失败,因为第二个函数找不到第一个函数,即使它位于命名空间之外。我自己无法弄清楚问题所在,到目前为止我还没有在网上找到任何答案。
test.cpp:
#include <bits/stdc++.h>
struct myclass ;
template <typename T, typename U>
std::ostream& operator<< (std::ostream &os, const std::pair<T, U> &p)
os << "(" << p.first << ", " << p.second << ")";
return os;
namespace my
void operator<< (std::ostream os, myclass m)
std::cout << std::pair<int, int>(5, 4); // This is line 13.
int main()
return 0;
编译器给出的错误 (g++ test.cpp -O2 -o test.exe
):test.cpp:13:13: error: no match for 'operator<<' (operand types are 'std::ostream aka std::basic_ostream<char>' and 'std::pair<int, int>')
.
它继续,给出了一长串关于operator<<
可能意味着什么的建议。
观察1:如果两个函数名称不同,不会出错。观察2:如果namespace my
去掉,不会出错发生。
【问题讨论】:
相关/欺骗:***.com/questions/25133383/… 通过显式调用全局运算符:::operator<<(std::cout, std::pair<int, int>(5, 4));
它应该可以工作,但这非常丑陋(并且不可链接)。如果有更好的方法,我不会将其发布为答案。
更好的方法是在调用前使用 using 指令 (using ::operator<<;
)。至于为什么查找最终没有在全局命名空间中找到候选人......
【参考方案1】:
这是一种名字隐藏;函数/运算符不能通过不同的作用域重载。
根据name lookup的规则,
(强调我的)
...,名称查找检查如下所述的范围,直到找到至少一个任何类型的声明,此时查找停止并且不再检查范围。
对于这种情况,名称operator<<
在名称空间my
(即其自身)的范围内找到,然后名称查找停止,不会检查全局范围,也不会检查全局operator<<
考虑以下重载解决方案。
还有
观察1:如果两个函数名称不同,则不会发生错误。
很好,因为没有隐藏名字。
观察 2:如果命名空间 my 被删除,则不会发生错误。
这很好,因为这两个operator<<
放在同一个范围内,即全局命名空间。然后可以找到operator<<
,然后在重载决议时考虑,最后选择合适的。
按照 cmets 的建议,您可以申请 using
将全局命名空间中的名称引入命名空间 my
;那么operator<<
都会被找到,然后在重载决议中考虑。
【讨论】:
【参考方案2】:namespace my
中定义的operator<<
可防止重载决议考虑您在全局命名空间中定义的operator<<
。您只能在此处依赖 ADL 或在当前范围内带来所需的重载:
namespace my
std::ostream& operator<<(std::ostream& os, myclass m)
// Bringing the operator in the global namespace in the current scope
using ::operator<<;
std::cout << std::pair<int, int>(5, 4);
【讨论】:
或更明确地说:::operator<<(std::cout, std::pair<int, int> 5, 4 );
我更喜欢 using 解决方案,因为它仍然允许 ADL以上是关于C++ 在命名空间中找不到函数的主要内容,如果未能解决你的问题,请参考以下文章
在 Xamarin Studio 中找不到类型或命名空间名称“页面”
在 mapActions() 中找不到 vuex 模块命名空间:taskModule/?
更改命名空间时在 Laravel 中找不到类“\App\User”