2010-02-05 28 views
12

Me gustaría definir un operador binario en el espacio de nombre global. El operador trabaja en una clase que está definida en otro espacio de nombres y el operador debe obtener el acceso a los miembros privados de esa clase. El problema que tengo es que no conozco el alcance de ese operador global cuando lo hago amigo en la definición de la clase.¿Cómo puedo definir amigos en el espacio de nombres global dentro de otro espacio de nombres C++?

he intentado algo así como:

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; 
    ... 
} 

El compilador (g ++ 4.4) que no sabía qué hacer con él. Parece que la línea

friend A ::operator *() 

se evalúa como algo parecido (pseudo-código)

(A::operator) 

en lugar de

(A) (::operator) 

Si dejo el :: en la declaración de la Operador de la compilación funciona pero el operador se encuentra en el espacio de nombres NOMBRE y no en el espacio de nombres global.

¿Cómo califico el espacio de nombre global en una situación así?

Respuesta

15

En primer lugar, tenga en cuenta que su declaración operador le faltaba un título de espacio de nombres para A:

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

y luego el truco decisiva es agregar paréntesis, a la declaración amigo como este, al igual que usted propuso en su "pseudo -code"

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

para hacer que todo compilar, este caso es necesario algunas declaraciones adelantadas, al llegar a este:

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 tiene razón, sin embargo, probablemente debería declarar al operador en el mismo espacio de nombres como sus parámetros.

+0

Eso es 3 respuestas casi idénticas ahora :-) – finnw

+0

Seguramente, te refieres * solo * tres :) –

3

No sé la respuesta exacta a su pregunta.

Pero es terriblemente mala idea definir el operador fuera del espacio de nombre de sus parámetros (ahora se corta la búsqueda dependiente del argumento que es muy útil para los operadores).

+2

+1. Si bien esta respuesta corta la raíz del problema, un pequeño detalle: si el op * está en alcance global, entonces no necesita ADL, ya que la función siempre está disponible. (No estoy seguro, pero tal vez el OP no entendía ADL y así se le ocurrió esto?) –

4

Esto compila, supongo sin probar que también funciona. Tenga en cuenta el uso de los paréntesis:

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() {} 

Como se menciona Alexander, sin embargo, su pregunta no explica por qué el operador no está a nombre de espacio de nombres. De cualquier manera, se puede llamar como 1.0 * some_A_instance. Entonces puedes estar creando problemas innecesarios para ti.

+0

Maldición, me ganaste por unos 20 segundos. Código casi idéntico también. – finnw

+0

Eso nos hace tres ahora, supongo ... –

+0

Genial, me salvaste el día. No estaba al tanto del hecho de que el operador puede residir en NAME y seguir trabajando de la manera que yo quería. – Andreas

2

Es posible - se puede encerrar el declarador entre paréntesis: friend A (::operator * (double lhs, const A& rhs));

También es necesario con visión de declarar tanto la clase y la función.

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) { 
    //... 
} 

Pero estoy de acuerdo con Andreas en que es mejor definir ambos en el mismo espacio de nombres si es posible.

Cuestiones relacionadas