Форум » C/C++ » Дружественные функции и общий баг известных компиляторов » Ответить

Дружественные функции и общий баг известных компиляторов

Сыроежка: Согласно стандарту C++ 17 (10.3.1.2 Namespace member definition) [quote]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[/quote] С другой стороны [quote]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). [/quote] То есть если дружественная функция впервые объявлена в классе, то ее имя будет невидимо до тех пор, пока не появится объявление этой функции в замыкающем пространстве имен. А из этого следует, что раз имя функции невидимо, то функция не может быть определена во внешнем пространстве имен, так как требуется поиск квалифицированного имени функции. Рассмотрим следующую демонстрационную программу. [pre2] #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 ); } [/pre2] Так как дружественная классу 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, это выдает следующие предупреждения [pre2] 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 & ); | ^[/pre2] Это тот редкий случай, когда даже если программа компилируется всеми широко известными компиляторами, это совершенно не означает, что программа корректная. А ведь часто программисты, которые не заглядывают в стандарта C++ , часто в качестве аргумента, что некоторая программа является корректной, ссылаются на то, что программа компилируется всеми широко известными компиляторами.

Ответов - 0



полная версия страницы