Вызов функции-друга, определенной в структуре, требует предварительного объявления? - PullRequest
5 голосов
/ 29 августа 2010

Читая Карлссона Вне стандарта C ++ , автор определил функцию друга intrusive_ptr_add_ref в теле class reference_counting (см. Стр. 36). Эта функция вызывается автоматически с использованием Argument Dependent Lookup в нужный момент.

Никогда не видя функции друзей, определенные в теле класса, я поиграл и обнаружил, что gcc 4.4.3 требует предварительного объявления, если не используется поиск ADL. На самом деле, кажется, что нет никакого способа сослаться на adl_no без этой предварительной декларации. Это часть стандарта C ++ или артефакт gcc? (У меня нет окна Windows, поэтому я не могу попробовать VC).

#include <cstdlib>
#include <iostream>


namespace {
    void adl_no();        // Remove this and it won't compile with gcc

    struct Q {
        friend void adl_yes(const Q&) {
            std::cout << "adl_yes" << std::endl;
        }

        friend void adl_no() {
            std::cout << "adl_NO" << std::endl;
        }
    };
}


int main(int argc, char** argv)
{
    adl_yes(Q());
    adl_no();

    return EXIT_SUCCESS;
}

1 Ответ

6 голосов
/ 29 августа 2010

Да, это стандартное поведение. Соответствующая часть стандарта - 7.3.1.2 [namespace.memdef], пункт 3:

Если объявление friend в нелокальном классе сначала объявляет класс или функцию, дружественный класс или функция является членом внутреннего вложенного пространства имен. Имя друга не будет найдено простым поиском имени, пока не будет предоставлено соответствующее объявление в этой области пространства имен [...]. Если вызывается функция друга, ее имя может быть найдено с помощью поиска имен, который рассматривает функцию из пространств имен и классов, связанных с типами аргументов функции (3.4.2) [т.е. ADL].

...