Lut.
Dans c++03, la d�claration d'une class friend ne peut pas �tre un type d�pendant. En gros, on ne peut pas faire ceci:
Maintenant si T est lui m�me param�tr� par rapport � A, �a ne va pas arranger les choses.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6 template<typename T> struct A { // illegal. "T" est un template argument friend class T; };
Pour comprendre ce que je souhaite faire, voici un code r�duit au minimum, qui fonctionne et qui fait intervenir les bonnes vieilles notions de Car et Engine
Ce que je souhaiterais faire pour la class engine est ceci:
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include<iostream> template<typename Engine> struct car { void start() { Engine e; e.priv = 1; std::cout << e.priv; } }; struct engine { // members... private: // seul un "car" est sensé instancier un engine engine() : priv(0) { } int priv; // OK. mais prob: le type "car" est trop spécifique template<typename Engine> friend class car; }; int main() { car<engine> c; c.start(); return 0; }
On comprend tout de suite que les types car et engine sont mutuellement corr�l�s et on tombe sur un probl�me de d�claration r�cursive (en plus du probl�me de d�claration du friend).
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 // pas bon. ridicule. // pas bon non plus avec template<template<typename T> class Car> template<typename Car> struct engine { // members... private: engine() : priv(0) { } int priv; // illegal. "Car" est un template argument template<typename Engine> friend class Car; };
Pour contourner le probl�me, j'ai fait ceci:
- la classe car d�rive d'une class template car_base qui sera friend de engine:
- le type param�tr� car_base est d�clar� friend de engine:
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 template<typename Engine> struct car_base { // membres pour accéder à certains membres privates de Engine }; template<typename Engine> struct car : public car_base<Engine> { typedef car_base<Engine> base_type; void start() { // utilise les membres de base_type pour accéder // à l'interface privée de Engine } };
Je peux maintenant composer avec des types raffin�s tel que advanced_car ou advanced_engine:
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8 struct engine { // members... // ... // OK. "car_base" est friend template<typename Engine> friend class car_base; };
En conclusion, Car peut varier ind�pendamment de Engine. La contrainte est que Engine reste compatible avec la fa�ade que constitue car_base.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11 template<typename Engine> struct advanced_car : public car_base<Engine> { // .. } advanced_car<engine> ac; car<advanced_engine> aac; advanced_car<advanced_engine> aaac;
Tout ceci est destin� � �tre utilis� dans un context plus vaste bas� sur les policies. Je me fiche que advanced_car ne d�rive pas de car dans l'exemple.
Est-ce que ce "trick" de la base classe param�tr�e qui sera friend de son param�tre vous parait pertinent. Une autre solution ?
Partager