2009-10-21 34 views
9

Tengo un problema que si tengo una clase de plantilla, que a su vez tiene un método de plantilla que toma un parámetro de otra instancia de la clase (con diferentes argumentos de plantilla), que no puede acceso protegido o miembros privados de la clase pasa como un parámetro, por ejemplo:C++ Problema de acceso de miembro de clase con plantillas

template<typename T>class MyClass 
{ 
    T v; 
public: 
    MyClass(T v):v(v){} 

    template<typename T2>void foo(MyClass<T2> obj) 
    { 
     std::cout << v  << " "; 
     //error C2248: 'MyClass<T>::v' : cannot access private member declared in class 'MyClass<T>' 
     std::cout << obj.v << " "; 
     std::cout << v + obj.v << std::endl; 
    } 
}; 
int main() 
{ 
    MyClass<int> x(5); 
    MyClass<double> y(12.3); 
    x.foo(y); 
} 

¿hay alguna manera de decir que los métodos en MiClase <T> tienen acceso completo a MiClase <SomeOtherT>?

Respuesta

9

Son tipos diferentes: construcciones de plantillas nuevas tipos de una plantilla.

usted tiene que hacer otras instancias de sus amigos de clase:

template <typename T>class MyClass 
{ 
    T v; 
public: 
    MyClass(T v):v(v){} 

    template<typename T2>void foo(MyClass<T2> obj) 
    { 
     std::cout << v  << " "; 
     std::cout << obj.v << " "; 
     std::cout << v + obj.v << std::endl; 
    } 

    // Any other type of MyClass is a friend. 
    template <typename U> 
    friend class MyClass; 

    // You can also specialize the above: 
    friend class MyClass<int>; // only if this is a MyClass<int> will the 
           // other class let us access its privates 
           // (that is, when you try to access v in another 
           // object, only if you are a MyClass<int> will 
           // this friend apply) 
}; 
+0

Glee! : D [15char] – GManNickG

+0

Su código en realidad no se compila en Comeau y no puedo encontrar cómo lo permite Standard. Creo que 'template' before' friend' es necesario debido a 14.5.3/3. –

+0

De hecho, también tuve eso :(Lo eliminé porque pensé que no era necesario. (Después de probarlo en VS) No debería probar con eso ... Lo volveré a agregar. ¡Bah! – GManNickG

7

Añadir MyClass como clase friend:

template<typename T> class MyClass 
{ 
    template<typename TX> 
    friend class MyClass; 
... 

Según C++ estándar 14.5.3/3:

Se puede declarar una plantilla de amigo dentro de una clase o plantilla de clase. Se puede definir una plantilla de función amiga dentro de una clase o plantilla de clase, pero una plantilla de clase amiga no se puede definir en una clase o plantilla de clase. En estos casos, todas las especializaciones de la clase de amigo o plantilla de función de amigo son amigos de la clase o plantilla de clase que otorga amistad. [Ejemplo:

class A { 
    template<class T> friend class B; // OK 
    template<class T> friend void f(T){ /* ... */ } // OK 
}; 

-fin ejemplo]

NOTA: Usted debe saber que el código anterior aún podría conducir a un error con algunos compiladores debido a Core Issue #602 que todavía está abierta. A pesar de esto, el código anterior compila en GCC, Visual C++ y Comeau.

Para hacer única función foo un amigo que podría escribir lo siguiente:

template<typename T> class MyClass 
{ 
    template<typename TY> template<typename TX> 
    friend void MyClass<TY>::foo(MyClass<TX>); 
... 
+0

por lo tanto, este código hace MiClase un amigo de MiClase para todos TX. ¿es posible hacer solamente MiClase :: foo un amigo en lugar de toda la clase? – user200783

+0

@ Pablo, he actualizado la respuesta. –

Cuestiones relacionadas