#cpp
почему код с templateкомпилируется, а без него нет #include using namespace std; struct a { friend void operator+(const a&, int) { cout << "ddd"; } } A; template struct c { operator a&() const noexcept { return A; } operator a() const noexcept { return A; } }; int main() { c C{}; C + 1; return 0; }
Ответы
Ответ 1
Если функция объявлена только как friend внутри класса, то она формально принадлежит охватывающему пространству имен. Но при этом она не видна обычному процессу поиска имен, а может быть видна лишь ADL-поиску (Argument Dependent Lookup). ADL-поиск делается через ассоциированные пространства имен и ассоциированные классы. Если один из аргументов имеет тип специализированного шаблона, то в список ассоциированных классов будут добавлены все типы аргументов этого шаблона. В вашем примере поиск подходящего оператора + производится в глобальном пространстве имен. Один из аргументов + является специализацией шаблона c с аргументом a. Это приводит к включению a в список ассоциированных классов и к тому, что friend-функции этого класса становится видимыми с точки зрения ADL в глобальном пространстве имен. Если вы уберете шаблонность, то класс a будет совершенно посторонним классом, никак не фигурирующим в выражении C + 1. Он не будет рассматриваться ADL в качестве ассоциированного класса и его friend-функции так и останутся "невидимыми". Если вы дополнительно явно объявите свой оператор в охватывающем пространстве имен struct a { friend void operator+(const a&, int) { cout << "ddd"; } } A; void operator+(const a&, int); тот он будет виден сразу и всегда обычному процессу поиска имен. Зависимость от ADL (и от шаблонности) сразу исчезнет и код будет компилироваться.
Комментариев нет:
Отправить комментарий