2011-07-25 10 views
10

Por favor, considere el código:C++ extern mundial amigo "C" no puede alcanzar miembro privado de la clase de espacio de nombres

#include <iostream> 

using namespace std; 

extern "C" 
void foo(void); 

namespace A 
{ 
    template< int No > 
    class Bar 
    { 
    private: 
     friend void ::foo(void); 

     static void private_func(int n); 
    }; 

    template< int No > 
    void Bar<No>::private_func(int n) 
    { 
     cout << "A:Bar< " << No << ">::private_func(" << n << ")" << endl; 
    } 
} 

extern "C" 
void foo(void) 
{ 
    A::Bar<0>::private_func(1); 
} 

int main() 
{ 
    cout << " ---- " << endl; 
    foo(); 
} 

G ++ da:

> g++ -Wall -o extern_c extern_c.cpp 
extern_c.cpp: In function ‘void foo()’: 
extern_c.cpp:20:7: error: ‘static void A::Bar<No>::private_func(int) [with int No = 0]’ is private 
extern_c.cpp:29:31: error: within this context 

Si comento el namspace A, se compilará y corre correctamente

¿Qué me estoy perdiendo?

Busqué temas relacionados, pero no encontré ninguno que se ajuste a mi problema.

Gracias gente.


EDIT:

ahora estoy convencido de que extern "C" no tiene nada que ver con el problema. Por favor ignórelo.

Respuesta

2

No sé la explicación, pero si coloca foo() en un espacio de nombres, funciona.

#include <iostream> 

using namespace std; 

namespace C 
{ 
    extern "C" 
    void foo(void); 
} 

namespace A 
{ 
    template< int No > 
    class Bar 
    { 
    private: 
     friend void C::foo(void); 

     static void private_func(int n); 
    }; 

    template< int No > 
    void Bar<No>::private_func(int n) 
    { 
     cout << "A::Bar< " << No << ">::private_func(" << n << ")" << endl; 
    } 
} 


namespace C 
{ 
    extern "C" 
    void foo(void) 
    { 
     A::Bar<0>::private_func(1); 
    } 
} 

int main() 
{ 
    cout << " ---- " << endl; 
    C::foo(); 
} 

Y el resultado:

[email protected] friends]$ g++ -Wall namespace_friend.cpp -o namespace_friend 
[[email protected] friends]$ ./namespace_friend 
---- 
A::Bar< 0>::private_func(1) 
+0

No será fácil poner mi 'foo()' real en un espacio de nombres porque es una rutina de servicio de interrupción, pero lo intentaré de todos modos. Gracias. – j4x

+1

Creo que este tipo tiene el mismo problema, pero ninguno ha sido respondido: http://stackoverflow.com/questions/2236712/how-do-i-define-a-friend-class-from-the-global-namespace- in-another-namespace –

+0

Parece ser el mismo problema, pero la sugerencia de espacio de nombres vacía no funciona. Veo el mismo error. – j4x

0

Debes declarar al amigo como extern "C". La declaración de su amigo actual encuentra un amigo foo en el espacio de nombres global que tiene el nombre C++ mangling.

+0

¿Cuál es la sintaxis exacta? –

+0

O-ho. Si cambio la línea 14 a 'friend extern' C 'void :: foo (void); 'Recibo el error adicional' extern_c.cpp: 14: 22: error: id-esperado no calificado antes de la constante de cadena'. – j4x

4

Es un error de g ++. Existe en 4.4, fijado en 4.6.

UPD: Parece que se desencadena por una combinación de template y namespace. extern "C" no es relevante, ya que puede ser comentada y el error permanece.

+0

¿Puedes citar una referencia? –

+0

'g ++ (SUSE Linux) 4.5.1 20101208 [gcc-4_5-branch revision 167585]'. Buscaré un 4.6 y le diré si funciona. – j4x

+0

@Mark B: el estándar de C++ no parece indicar que las declaraciones de tus amigos se ignoren silenciosamente si eres una plantilla de clase incluida en un espacio de nombres. Concluyo que un compilador que lo hace debe estar en error. No puedo probarlo, excepto posiblemente citando todo el estándar. –

Cuestiones relacionadas