2010-02-05 15 views
12

Mi piacerebbe definire un operatore binario nello spazio dei nomi globale. L'operatore funziona su una classe definita in un altro spazio dei nomi e l'operatore deve ottenere l'accesso ai membri privati ​​di tale classe. Il problema che ho è che non lo so sapere come ambito quell'operatore globale quando lo si fa amico nella definizione della classe.Come definire gli amici nello spazio dei nomi globale all'interno di un altro spazio dei nomi C++?

ho provato qualcosa di simile:

namespace NAME 
{ 
    class A { 
     public: 
      friend A ::operator * (double lhs, const A& rhs); 
     private: 
      int private_var; 
    }; 
} 

A operator * (double lhs, const A& rhs) 
{ 
    double x = rhs.private_var; 
    ... 
} 

Il compilatore (g ++ 4.4) non sapeva che cosa fare con esso. Sembra che la linea

friend A ::operator *() 

viene valutato come qualcosa di simile (pseudo-codice)

(A::operator) 

invece di

(A) (::operator) 

Se lascio il :: nella dichiarazione del l'operatore la compilazione funziona ma l'operatore è quindi nello spazio dei nomi NOME e non nello spazio dei nomi globale.

Come posso qualificare lo spazio dei nomi globale in una situazione del genere?

risposta

15

In primo luogo, si noti che la dichiarazione di operatore mancava una qualificazione dello spazio dei nomi per A:

NAME::A operator * (double lhs, const NAME::A& rhs) 

e poi il trucco decisivo è quello di aggiungere le parentesi per la dichiarazione di un amico in questo modo, proprio come avete proposto nel vostro "pseudo -code"

friend A (::operator *) (double lhs, const A& rhs); 

per rendere il tutto compilare, è quindi necessario alcune dichiarazioni in avanti, arrivando a questo:

namespace NAME 
{ 
    class A; 
} 

NAME::A operator * (double lhs, const NAME::A& rhs); 

namespace NAME 
{ 
    class A { 
     public: 
      friend A (::operator *) (double lhs, const A& rhs); 
     private: 
      int private_var; 
    }; 
} 

NAME::A operator * (double lhs, const NAME::A& rhs) 
{ 
    double x = rhs.private_var; 
} 

Alexander ha ragione, tuttavia - dovresti probabilmente dichiarare l'operatore nello stesso spazio dei nomi dei suoi parametri.

+0

Ecco 3 risposte quasi identiche ora :-) – finnw

+0

Sicuramente, intendi * solo * tre :) –

3

Non so la risposta esatta alla tua domanda.

Ma è una pessima idea non definire l'operatore al di fuori dello spazio dei nomi dei suoi parametri (ora si riduce la ricerca dipendente dall'argomento che è molto utilizzabile per gli operatori).

+2

+1. Mentre questa risposta taglia alla radice del problema, un leggero nitpick: se l'op * è a portata globale, allora non hai bisogno di ADL, poiché la funzione è sempre disponibile. (Non ne sono sicuro, ma forse l'OP non ha capito ADL e così è venuto fuori con questo?) –

4

Compilando, presumo senza test che funzioni anche. Si noti l'uso delle parentesi:

namespace NAME {class A; } 
NAME::A operator * (double lhs, const NAME::A& rhs); 

namespace NAME 
{ 
    class A { 
     public: 
      friend A (::operator *) (double lhs, const A& rhs); 
     private: 
      int private_var; 
    }; 
} 

NAME::A operator * (double lhs, const NAME::A& rhs) 
{ 
    double x = rhs.private_var; 
    return rhs; 
} 

int main() {} 

Come cita Alexander, però, la sua domanda non spiega perché l'operatore non è in nome del namespace. Ad ogni modo può essere chiamato come 1.0 * some_A_instance. Quindi potresti creare problemi inutili per te stesso.

+0

Darn, mi hai battuto per circa 20 secondi. Anche il codice quasi identico. – finnw

+0

Questo ci rende tre ora, immagino ... –

+0

Ottimo, hai salvato la mia giornata. Non ero a conoscenza del fatto che l'operatore può risiedere in NAME e funziona ancora come volevo. – Andreas

2

E 'possibile - si può racchiudere il dichiaratore tra parentesi: friend A (::operator * (double lhs, const A& rhs));

È inoltre necessario inoltrare-dichiarare sia la classe e la funzione.

namespace NAME {class A;} 
NAME::A operator *(double lhs, const NAME::A& rhs); 

// ... 

namespace NAME 
{ 
    class A { 
     public: 
      friend A (::operator * (double lhs, const A& rhs)); 
     private: 
      int private_var; 
    }; 
} 

NAME::A operator *(double lhs, const NAME::A& rhs) { 
    //... 
} 

Ma concordo con Andreas sul fatto che sarebbe meglio definire entrambi nello stesso spazio dei nomi, se possibile.

Problemi correlati