Disons que je crée une classe pour un arbre binaire, BT
, et que j'ai une classe qui décrit un élément de l'arbre, BE
, quelque chose comme
template<class T> class BE {
T *data;
BE *l, *r;
public:
...
template<class U> friend class BT;
};
template<class T> class BT {
BE<T> *root;
public:
...
private:
...
};
Cela semble fonctionner; Cependant, j'ai des questions sur ce qui se passe en dessous.
J'ai d'abord essayé de déclarer l'ami comme
template<class T> friend class BT;
cependant, il semble nécessaire d'utiliser U
(ou autre chose que T
) ici, pourquoi? Cela implique-t-il que tout BT
particulier est ami d'une classe BE
particulière?
La page IBM consacrée aux modèles et aux amis contient des exemples de types de relations d'amis différents pour les fonctions mais pas pour les classes (et deviner une syntaxe n'a pas encore convergé vers la solution). Je préférerais comprendre comment adapter les spécifications au type de relation d'ami que je souhaite définir.
template<class T> class BE{
template<class T> friend class BT;
};
N'est pas autorisé car les paramètres de modèle ne peuvent pas se masquer. Les modèles imbriqués doivent avoir des noms de paramètre différents.
template<typename T>
struct foo {
template<typename U>
friend class bar;
};
Cela signifie que bar
est un ami de foo
quels que soient les arguments de template de bar
. bar<char>
, bar<int>
, bar<float>
, et tout autre bar
serait un ami de foo<char>
.
template<typename T>
struct foo {
friend class bar<T>;
};
Cela signifie que bar
est un ami de foo
lorsque l'argument de modèle de bar
correspond à celui de foo
. Seulement bar<char>
serait un ami de foo<char>
.
Dans ton cas, friend class bar<T>;
devrait suffire.
Afin de créer des liens avec une autre structure de même type:
#include <iostream>
template<typename T_>
struct Foo
{
// Without this next line source.value_ later would be inaccessible.
template<typename> friend struct Foo;
Foo(T_ value) : value_(value) {}
template <typename AltT>
void display(AltT &&source) const
{
std::cout << "My value is " << value_ << " and my friend's value is " << source.value_ << ".\n";
}
protected:
T_ value_;
};
int main()
{
Foo<int> foo1(5);
Foo<std::string> foo2("banana");
foo1.display(foo2);
return 0;
}
Avec la sortie comme suit:
My value is 5 and my friend's value is banana.
Dans template<typename> friend struct Foo;
vous ne devriez pas écrire T
après typename
/class
, sinon cela provoquerait une erreur d’observation des paramètres du template.
Il n'est pas nécessaire de nommer les paramètres pour réduire le nombre de points d'échec lors du refactoring:
template <typename _KeyT, typename _ValueT> class hash_map_iterator{
template <typename, typename, int> friend class hash_map;
...