2009-10-21 9 views
9

J'ai rencontré un problème si j'ai une classe template, qui à son tour a une méthode template qui prend un paramètre d'une autre instance de la classe (avec des arguments templates différents), qu'elle ne peut pas accès membres protégés ou privés de la classe passée en paramètre, par exemple:Problème d'accès des membres de classe C++ avec les modèles

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

Est-il someway dire que les méthodes dans MyClass <T> ont accès à MyClass <SomeOtherT>?

Répondre

9

Ce sont des types différents: les modèles construisent nouveaux types à partir d'un modèle.

Vous devez faire d'autres instanciations de vos camarades de classe:

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

Votre code ne compile pas réellement dans Comeau et je ne peux pas trouver comment Standard le permet. Je crois que 'template' avant' friend' est nécessaire en raison de 14.5.3/3. –

+0

Je l'avais aussi :(Je l'ai enlevé parce que je pensais que c'était inutile. (Après avoir testé en VS) Je ne devrais vraiment pas tester avec ça ... Je vais le rajouter. Bah! – GManNickG

7

Ajouter MyClass comme classe ami:

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

Selon C++ standard 14.5.3/3:

Un modèle d'ami peut être déclaré dans un modèle de classe ou de classe. Un modèle de fonction ami peut être défini dans un modèle de classe ou de classe, mais un modèle de classe ami peut ne pas être défini dans un modèle de classe ou de classe. Dans ce cas, toutes les spécialisations du modèle de fonction friend ou friend sont des amis du modèle de classe ou de classe accordant l'amitié. [Exemple:

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

-end exemple]

REMARQUE: Vous devez savoir que le code ci-dessus pourrait encore conduire à une erreur avec des compilateurs en raison de Core Issue #602 qui est encore ouvert. Malgré cela, le code ci-dessus compile sur GCC, Visual C++ et Comeau.

Pour faire la seule fonction foo un ami, vous pouvez écrire:

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

Ainsi, ce code fait MyClass un ami de MyClass pour tous TX. Est-il possible de ne faire que MyClass :: foo un ami – user200783

+0

plutôt que la classe? @ Paul, je l'ai mis à jour la réponse. –

Questions connexes