C ++ не может найти функцию из пространства имен - PullRequest
0 голосов
/ 22 февраля 2019

Компиляция следующего кода завершается неудачно, потому что вторая функция не может найти первую, даже если она находится за пределами пространств имен.Я не мог понять проблему сам, и до сих пор я не нашел никаких ответов в сети.

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 { } удалено, ошибки не возникает.

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

Это своего рода сокрытие имени;функции / операторы не могут быть перегружены через разные области.

В соответствии с правилом поиск имени ,

(выделено мной)

..., поиск имени проверяет области, как описано ниже, до тех пор, пока не найдет хотя бы одну декларацию любого вида, в этот момент поиск останавливается и дальнейшие области не проверяются .

В этом случае имя operator<< находится в области имен my (т.е. само по себе), затем поиск по имени останавливается, глобальная область не будет проверяться, глобальная operator<< не будетрассматривается для следующего разрешения перегрузки.

И

Замечание 1: Если две функции отличаются по имени, ошибки не возникает.

Это нормально, потому чтоимя не скрывается.

Замечание 2: Если пространство имен my {} удалено, ошибки не возникает.

Это нормально, потому что два operator<< ставятся ната же область, то есть глобальное пространство имен.Затем оба operator<< могут быть найдены и затем рассмотрены с разрешением перегрузки, в конце концов будет выбран соответствующий.

В соответствии с предложенными комментариями вы можете применить using, чтобы ввести имена в глобальном пространстве имен в пространство именmy;тогда оба значения operator<< будут найдены, а затем рассмотрены в разрешении перегрузки.

0 голосов
/ 22 февраля 2019

operator<<, определенное в namespace my, не позволяет разрешению перегрузки учитывать ваше 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);
}

}
...