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&lt;&lt;' (operand types are 'std::ostream aka std::basic_ostream&lt;char&gt;' and 'std::pair&lt;int, int&gt;'). 它继续,给出了一长串关于operator&lt;&lt;可能意味着什么的建议。

观察1:如果两个函数名称不同,不会出错。观察2:如果namespace my 去掉,不会出错发生。

【问题讨论】:

相关/欺骗:***.com/questions/25133383/… 通过显式调用全局运算符:::operator&lt;&lt;(std::cout, std::pair&lt;int, int&gt;(5, 4)); 它应该可以工作,但这非常丑陋(并且不可链接)。如果有更好的方法,我不会将其发布为答案。 更好的方法是在调用前使用 using 指令 ​​(using ::operator&lt;&lt;;)。至于为什么查找最终没有在全局命名空间中找到候选人...... 【参考方案1】:

这是一种名字隐藏;函数/运算符不能通过不同的作用域重载。

根据name lookup的规则,

(强调我的)

...,名称查找检查如下所述的范围,直到找到至少一个任何类型的声明,此时查找停止并且不再检查范围

对于这种情况,名称operator&lt;&lt; 在名称空间my(即其自身)的范围内找到,然后名称查找停止,不会检查全局范围,也不会检查全局operator&lt;&lt;考虑以下重载解决方案。

还有

观察1:如果两个函数名称不同,则不会发生错误。

很好,因为没有隐藏名字。

观察 2:如果命名空间 my 被删除,则不会发生错误。

这很好,因为这两个operator&lt;&lt; 放在同一个范围内,即全局命名空间。然后可以找到operator&lt;&lt;,然后在重载决议时考虑,最后选择合适的。

按照 cmets 的建议,您可以申请 using 将全局命名空间中的名称引入命名空间 my;那么operator&lt;&lt; 都会被找到,然后在重载决议中考虑。

【讨论】:

【参考方案2】:

namespace my 中定义的operator&lt;&lt; 可防止重载决议考虑您在全局命名空间中定义的operator&lt;&lt;。您只能在此处依赖 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&lt;&lt;(std::cout, std::pair&lt;int, int&gt; 5, 4 ); 我更喜欢 using 解决方案,因为它仍然允许 ADL

以上是关于C++ 在命名空间中找不到函数的主要内容,如果未能解决你的问题,请参考以下文章

在 Xamarin Studio 中找不到类型或命名空间名称“页面”

在命名空间/头文件中找不到类

在 mapActions() 中找不到 vuex 模块命名空间:taskModule/?

更改命名空间时在 Laravel 中找不到类“\App\User”

在命名空间中找不到 System.Text.Json.JsonReaderException

MVC项目中找不到DbContext命名空间