On-line: гостей 0. Всего: 0 [подробнее..]
Программисты всех стран, объединяйтесь!

АвторСообщение



ссылка на сообщение  Отправлено: 18.12.19 14:58. Заголовок: Дружественные функции и общий баг известных компиляторов


Согласно стандарту C++ 17 (10.3.1.2 Namespace member definition)


 цитата:
2 Members of a named namespace can also be defined outside that namespace by explicit qualification (6.4.3.2) of the name being defined, provided that the entity being defined was already declared in the namespace and the definition appears after the point of declaration in a namespace that encloses the declaration’s namespace



С другой стороны


 цитата:
3 Ifafrienddeclarationinanon-localclassfirstdeclaresaclass,function,classtemplateorfunctiontemplate97 the friend is a member of the innermost enclosing namespace. The friend declaration does not by itself make the name visible to unqualified lookup (6.4.1) or qualified lookup (6.4.3).



То есть если дружественная функция впервые объявлена в классе, то ее имя будет невидимо до тех пор, пока не появится объявление этой функции в замыкающем пространстве имен.

А из этого следует, что раз имя функции невидимо, то функция не может быть определена во внешнем пространстве имен, так как требуется поиск квалифицированного имени функции.

Рассмотрим следующую демонстрационную программу.
 
#include <iostream>

namespace N1
{
inline namespace N2
{
class A
{
public:
friend void f( const A & );
private:
int x = 10;
};

//void f( const A & );
}

void N2::f( const A &a ) { std::cout << a.x << '\n'; }
}

int main()
{
using namespace N1;

A a;

f( a );
}

Так как дружественная классу A функция f не объявлена нигде в пространстве имен N2 за исключением ее объявления в самом классе, то ее имя невидимо в пространстве имен N2. Следовательно поиск квалифицированного имени функции в пространстве имен N1 завершится неуспешно, и программа является некорректной.

Тем не менее, все три компилятора, gcc HEAD 10.0.0 20191, clang HEAD 10.0.0 и Visual C++ 2019 компилируют эту программу. Единственное, что делает компилятор gcc HEAD 10.0.0 20191, это выдает следующие предупреждения
 
rog.cc:18:10: warning: 'void N1::N2::f(const N1::N2::A&)' has not been declared within 'N1::N2'
18 | void N2::f( const A &a ) { std::cout << a.x << '\n'; }
| ^~
prog.cc:10:25: note: only here as a 'friend'
10 | friend void f( const A & );
| ^


Это тот редкий случай, когда даже если программа компилируется всеми широко известными компиляторами, это совершенно не означает, что программа корректная. А ведь часто программисты, которые не заглядывают в стандарта C++ , часто в качестве аргумента, что некоторая программа является корректной, ссылаются на то, что программа компилируется всеми широко известными компиляторами.

Спасибо: 0 
ПрофильЦитата Ответить
Новых ответов нет


Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 4
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет