Newsgroup: it.comp.lang.c++
Titolo: Scope dei namespaces

Guardate questo esempio:
[ghigo@therra tmp]$ cat prova.cpp
#include <iostream>
using namespace std;
namespace A {
        struct X { int a; };
        void effe( X x ){ cout << "A::effe(" << x.a << ")" << endl; }
        void gi( int i ){ cout << "A::gi("<<i<<")"<<endl; }
}
void effe( A::X x ){ cout << "effe("<<x.a<<")"<<endl; }
void gi( int i ){ cout << "gi("<<i<<")"<<endl; }
int main( ){
        A::X    x={0};
        effe(x);
        A::effe(x);
        gi(3);
        A::gi(3);
}
[ghigo@therra tmp]$ g++-3.0.1 -Wall -ansi -pedantic -o prova prova.cpp
prova.cpp: In function `int main()':
prova.cpp:18: call of overloaded `effe(A::X&)' is ambiguous
prova.cpp:12: candidates are: void effe(A::X)
prova.cpp:8:                 void A::effe(A::X)
In pratica A::effe( ) e ::effe( ) hanno la stessa visibilità perché hanno 
come argomento un tipo del namespace A.
Mentre ::gi( ) e A::gi( ) hanno visibilità diverse perché *non* hanno come 
argomento un tipo del namespace A.
Quando me lo hanno fatto notare NON ci volevo credere, ma invece l'evidenza 
sperimentale dimostra che ciò è un comportamento voluto.
La domanda ora è perché ?

 La domanda ora e' perche' ?
si tratta della "Koenig-lookup", secondo la quale la funzione viene
ricercata, oltre che nel namespace globale anche nei namespace
dei suoi argomenti, ed e' stata introdotta per permettere
di definire degli operatori dentro i namespace.
Se ad esempio hai
namespace A
{
   X  operator + (const &X, const &X );
} 
puoi scrivere 
main()
{
   X x1, x2; 
   ...
   X x3 = x1 + x2;
}
invece di  A::operator +(x1, x2);
Ovviamente se l'operator +(const &X, const &X) e' definito
sia nel namespace A che in quello globale, il compilatore
non sa cosa scegliere.
In tal caso saresti costretto a specificare esplicitamente
lo scope.
Nel tuo esempio dovresti chiamare ::effe(x) e A::effe(x)
per distinguere le due funzioni.
(Ma una cosa del genere indica comunque dei gravi problemi
di design ;-)
Saluti,
Fabio
-- 
Posted from 
flopiano.mm.eutelsat.org
 [194.214.173.28] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 La domanda ora è perché ?
per colpa (merito?) della "Koening name lookup", indispensabile quando 
fai l'overload degli operatori di una classe contenuta in un namespace.
Se ci pensi la utilizzi tutti i giorni:
        std::cout << 10
il compilatore vede che cout e' nel namespace std e quindi cerca anche 
in esso gli operatori validi, trovando std::operator<<(std::ostream&, 
int). Se non ci fosse la Koening lookup l'unico modo per chiamare 
quell'operatore senza fare "using namespace std" sarebbe questo:
        std::operator<<( std::cout, 10 );
Non e' molto bello, vero?
Su "Exceptional C++" di Sutter trovi una esauriente spiegazione della 
Koening lookup.
ciao Anto
-- 
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

 invece di  A::operator +(x1, x2);
Forse mi sbaglio, ma questo esempio non mi sembra metta in evidenza il
vantaggio del "Koeing Lookup".
In questo caso il compilatore cerca se operator+ è definito nel namespace di
x1 e x2 (giusto?). Ma questi si trovano definiti nel main... quindi che
senso ha?
puoi chiarirmi le idee?
Grazie
--
Luigi
http://web.tiscali.it/luigi_web
byte...@hotmail.com
ICQ 46240443

 main... quindi che senso ha?
no. Quando hai questo:
        ClasseX istanzaX;
        ClasseY istanzaY;
        istanzaX + istanzaY;
Per risolvere la chiamata il compilatore cerca gli operatori nei 
seguenti namespace:
- il namespace "corrente" o tutti i suoi "padri"
- il namespace dove e` definita ClasseX (e *non* istanzaX)
- il namespace dove e` definita ClasseY (e *non* istanzaY)


 - il namespace dove e` definita ClasseY (e *non* istanzaY)
Ah, ecco, era questo che mi ha fatto confondere.
Ciao
-- 
Luigi
Web Site: 
http://web.tiscali.it/luigi_web
E-mail: 
byte...@hotmail.com
ICQ #46240443