3.3.1 пункт 6. Означает ли это, что программа не должна работать?
//a.h
class A{
static void Talk(){std::cout<<"A::Talk()\n";}
friend void Some();
};
//main.cpp
#include "a.h"
int main(){
Some();
return 0;
}
//file1.cpp
#include "a.h"
void Some(){
A::Talk();
}
Не должна работать, так как имя Some не видно или я не так понял?
Должна работать. 3.3.1.6 означает, что friend, так как и extern, декларируют, но не определяют.
// a.h
extern void Some(); // extern declarations, but they not introduce void Some()
class A
{
friend void Some(); // friend declarations, but they not introduce void Some()
static test() {...}
};
// some.cpp
#include "a.h"
void Some()
{
A::test();
}
// main.cpp
#include "a.h"
int main()
{
Some();
}
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте Fiend, Вы писали:
F>3.3.1 пункт 6. Означает ли это, что программа не должна работать?
<...>
F>Не должна работать, так как имя Some не видно или я не так понял?
Ты все правильно понял, если под "работать" ты имеешь в виду "компилироваться". Абзац 6 пункта 3.3.1 не является нормативным — это примечание, поэтому основанием служить не может. Однако, приведенный пример, как и его упрощенная версия,
компилироваться не должен:
class A{
static void Talk() { /*. . .*/ }
friend void Some();
};
int main()
{
Some();
return 0;
}
Основанием, как и указано в примечании 3.3.1/6, служит пункт
7.3.1.2, вот цитата из соответствующего нормативного абзаца: "
3 <...> The name of the friend is not found by simple name lookup until a matching declaration is provided in that namespace scope (either before or after the class declaration granting friendship)."
Достаточно интересный эффект возникает благодаря следующей его части: "If a friend function is called, its name may be found by the name lookup that considers functions from namespaces and classes associated with the types of the function arguments (3.4.2)."
Это, в частности означает, что функция foo в следующем пример может быть найдена только через поиск имен, зависящий от аргументов (aka Koenig lookup):
class C
{
public:
friend void foo(C&);
};
int main()
{
C c;
foo(c); // OK. функция должна быть найдена через Koenig lookup
::foo(c); // Ошибка. функция foo не объявлена
// (квалификация подавляет Koenig lookup)
void (*f)(C&) = &foo; // Ошибка. функция foo не объявлена
}
Этот пример относится только к компиляторам, корректно поддерживающим Koenig lookup.
Примечание: многие компиляторы позволяют себе игнорировать 7.3.1.2/3, компилируя все перечисленные примеры, что не является аргументом в пользу корректности последних.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен