c++ standard
От: Fiend  
Дата: 20.09.02 13:39
Оценка:
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 не видно или я не так понял?
Re: c++ standard
От: Анатолий СССР  
Дата: 20.09.02 14:10
Оценка:
Должна работать. 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(); 
}
Re: c++ standard
От: Sergey Россия  
Дата: 20.09.02 14:11
Оценка:
Здравствуйте Fiend, Вы писали:

F>3.3.1 пункт 6. Означает ли это, что программа не должна работать?


Это означает, что она не должна компилироваться.

F>Не должна работать, так как имя Some не видно или я не так понял?
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[2]: c++ standard
От: Fiend  
Дата: 20.09.02 14:18
Оценка:
Ну а если определение класса поместить в пространство имен?
Re[3]: c++ standard
От: Анатолий СССР  
Дата: 20.09.02 14:25
Оценка:
Ну и что?
Re: c++ standard
От: Павел Кузнецов  
Дата: 20.09.02 14:58
Оценка:
Здравствуйте 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, компилируя все перечисленные примеры, что не является аргументом в пользу корректности последних.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: c++ standard
От: Павел Кузнецов  
Дата: 20.09.02 14:59
Оценка:
Здравствуйте Анатолий, Вы писали:

А>Должна работать. 3.3.1.6 означает, что friend, так как и extern, декларируют, но не определяют.


Нет friend не объявляет функцию, а только объявлет ее friendship, п. 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)." То, что некоторые (многие) компиляторы позволяют себе игнорировать этот пункт, аргументом не является.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.