Friend di modelli
I template di classe possono avere friend.Il modello di classe o della classe, la funzione, o il modello di funzione possono essere friend in una classe modello.Friend possono anche essere specializzazioni del modello o di modello di funzione di classe, ma non specializzazioni parziali.
Esempio
Nell'esempio seguente, una funzione friend è definita come modello di funzione all'interno del modello di classe.Questo codice produce una versione della funzione friend per ogni creazione di un'istanza del modello.Questo costrutto è utile se la funzione friend dipende dagli stessi parametri di modello nella classe svolge.
// template_friend1.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
template <class T> class Array {
T* array;
int size;
public:
Array(int sz): size(sz) {
array = new T[size];
memset(array, 0, size * sizeof(T));
}
Array(const Array& a) {
size = a.size;
array = new T[size];
memcpy_s(array, a.array, sizeof(T));
}
T& operator[](int i) {
return *(array + i);
}
int Length() { return size; }
void print() {
for (int i = 0; i < size; i++)
cout << *(array + i) << " ";
cout << endl;
}
template<class T>
friend Array<T>* combine(Array<T>& a1, Array<T>& a2);
};
template<class T>
Array<T>* combine(Array<T>& a1, Array<T>& a2) {
Array<T>* a = new Array<T>(a1.size + a2.size);
for (int i = 0; i < a1.size; i++)
(*a)[i] = *(a1.array + i);
for (int i = 0; i < a2.size; i++)
(*a)[i + a1.size] = *(a2.array + i);
return a;
}
int main() {
Array<char> alpha1(26);
for (int i = 0 ; i < alpha1.Length() ; i++)
alpha1[i] = 'A' + i;
alpha1.print();
Array<char> alpha2(26);
for (int i = 0 ; i < alpha2.Length() ; i++)
alpha2[i] = 'a' + i;
alpha2.print();
Array<char>*alpha3 = combine(alpha1, alpha2);
alpha3->print();
delete alpha3;
}
L'esempio seguente comporta l'uso di un elemento friend con una specializzazione di template.Una specializzazione di template di funzione è automaticamente friend se il modello di funzione originale è friend.
È inoltre possibile dichiarare solo la versione specializzata del modello come friend, ad esempio il commento prima della dichiarazione friend nel codice seguente scegliere.In questo caso, è necessario inserire la definizione della specializzazione del template friend all'esterno della classe modello.
// template_friend2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
template <class T>
class Array;
template <class T>
void f(Array<T>& a);
template <class T> class Array
{
T* array;
int size;
public:
Array(int sz): size(sz)
{
array = new T[size];
memset(array, 0, size * sizeof(T));
}
Array(const Array& a)
{
size = a.size;
array = new T[size];
memcpy_s(array, a.array, sizeof(T));
}
T& operator[](int i)
{
return *(array + i);
}
int Length()
{
return size;
}
void print()
{
for (int i = 0; i < size; i++)
{
cout << *(array + i) << " ";
}
cout << endl;
}
// If you replace the friend declaration with the int-specific
// version, only the int specialization will be a friend.
// The code in the generic f will fail
// with C2248: 'Array<T>::size' :
// cannot access private member declared in class 'Array<T>'.
//friend void f<int>(Array<int>& a);
friend void f<>(Array<T>& a);
};
// f function template, friend of Array<T>
template <class T>
void f(Array<T>& a)
{
cout << a.size << " generic" << endl;
}
// Specialization of f for int arrays
// will be a friend because the template f is a friend.
template<> void f(Array<int>& a)
{
cout << a.size << " int" << endl;
}
int main()
{
Array<char> ac(10);
f(ac);
Array<int> a(10);
f(a);
}
Nell'esempio seguente viene illustrato un modello di classe friend dichiarato all'interno di un modello di classe.Il modello di classe verrà quindi utilizzato come argomento di template per la classe friend.I template di classe friend devono essere esterne definito un template di classe in cui sono dichiarati.Tutte le specializzazioni o le specializzazioni parziali del modello friend è friend del modello della classe.
// template_friend3.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
template <class T>
class X
{
private:
T* data;
void InitData(int seed) { data = new T(seed); }
public:
void print() { cout << *data << endl; }
template <class U> friend class Factory;
};
template <class U>
class Factory
{
public:
U* GetNewObject(int seed)
{
U* pu = new U;
pu->InitData(seed);
return pu;
}
};
int main()
{
Factory< X<int> > XintFactory;
X<int>* x1 = XintFactory.GetNewObject(65);
X<int>* x2 = XintFactory.GetNewObject(97);
Factory< X<char> > XcharFactory;
X<char>* x3 = XcharFactory.GetNewObject(65);
X<char>* x4 = XcharFactory.GetNewObject(97);
x1->print();
x2->print();
x3->print();
x4->print();
}