C++ can't find function out of namespace

假装没事ソ 提交于 2021-02-19 02:56:08

问题


Compiling the following code fails because the second function can't find the first one, even though it's outside namespaces. I couldn't figure out the problem myself, and so far I haven't found any answers on the net.

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;
}

Error given by the compiler (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>').
And it goes on, giving a long list of suggestions for what operator<< could have meant.

Observation 1: If the two functions differ in name, no error occurs.
Observation 2: If namespace my { } is removed, no error occurs.


回答1:


This is a kind of name hiding; functions/operators can't be overloaded through different scopes.

According to the rule of name lookup,

(emphasis mine)

..., name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.

For this case, the name operator<< is found at the scope of namespace my (i.e. itself), then name lookup stops, the global scope won't be examined, the global operator<< won't be considered for the following overload resolution.

And

Observation 1: If the two functions differ in name, no error occurs.

It's fine because there's no name hiding.

Observation 2: If namespace my { } is removed, no error occurs.

It's fine because the two operator<< is put at the same scope, i.e. the global namespace. Then both operator<< could be found and then considered at overload resolution, the appropriate one will be selected at last.

As the comments suggested, you can apply using to introduce the names in global namespace into namespace my; then both operator<< will be found and then considered in overload resolution.




回答2:


The operator<< defined in namespace my prevents overload resolution to consider your operator<< defined in the global namespace. You can only rely on ADL here or bring the desired overload in the current scope:

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);
}

}


来源:https://stackoverflow.com/questions/54829319/c-cant-find-function-out-of-namespace

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!