Précédent   Forum du club des développeurs et IT Pro > C et C++ > C++ > Langage
Langage Langage C++, Programmation Orientée Objet, Templates, etc. Avant de poster : FAQ C++
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 17/12/2012, 18h13   #1
Iradrille
Membre éprouvé
 
Homme
Étudiant
Inscription : juin 2012
Messages : 263
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2012
Messages : 263
Points : 443
Points : 443
Par défaut Templates, friends et ordre de déclaration

Hello,

J'ai un bout de code qui ressemble à ça
Code :
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
struct AbsMsg { };
 
template <class T>
struct Msg: public AbsMsg { };
 
template <class Impl, class... Args>
struct A {
	std::tuple<Args...> m_tuple;
	Impl m_impl;
	size_t m_step;
 
	void action(AbsMsg *msg) {
		// TODO jouer avec les templates pour "convertir" m_step en parametre template
		// et appeler m_impl.bar<m_step>(msg);
	}
};
 
struct I;
 
struct B : public A<I, int, char> {
	friend struct I;
};
 
struct I {
	template <size_t N>
	struct AlwaysFalse {
		enum { value = false; };
	};
 
	template <size_t N>
	void foo(Msg<typename std::tuple_element<N, decltype(m_tuple)>::type>* msg) {
		static_assert(AlwaysFalse<N>::value, "please implement");
	}
 
	template<>
	void foo<0>(Msg<int> *msg) { }
 
	template<>
	void foo<1>(Msg<char> *msg) { }
 
	template <size_t N>
	void bar(AbsMsg* msg) {
		foo<N>((Msg<typename std::tuple_element<N, decltype(m_tuple)>::type>*) msg);
	}
};
Le problème est que B a besoin de I complet (héritage / parametre template) et que I à besoin de B complet (friend).
Ya un moyen de s'en sortir ?

Ou une autre solution qui permettrait d'arriver au même résultat ?

Si seulement les fonctions template pouvaient etre virtuelles, foo irait dans A et serait spécialisée dans B et ça simplifierait tout ><
Iradrille est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/12/2012, 11h12   #2
leternel
Expert Confirmé
 
Homme Pierre
Ingénieur développement logiciels
Inscription : juin 2007
Messages : 1 185
Détails du profil
Informations personnelles :
Nom : Homme Pierre
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : juin 2007
Messages : 1 185
Points : 2 500
Points : 2 500
Regarde donc du coté de "l'implémentation privée" aussi appelée "pimpl", qui utilise un pointeur vers l'implémentation, et une redirection.
__________________
Mes principes de bases du codeur qui veut pouvoir dormir:
  • Une variable de moins est une source d'erreur en moins.
  • Un pointeur de moins est une montagne d'erreurs en moins.
  • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
  • La plus sotte des questions est celle qu'on ne pose pas.
leternel est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 20/12/2012, 19h02   #3
Iradrille
Membre éprouvé
 
Homme
Étudiant
Inscription : juin 2012
Messages : 263
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2012
Messages : 263
Points : 443
Points : 443
Citation:
Envoyé par leternel Voir le message
Regarde donc du coté de "l'implémentation privée" aussi appelée "pimpl", qui utilise un pointeur vers l'implémentation, et une redirection.
bien vu.
J'ai par contre été obligé d'implémenter "Impl" dans A, je voyais pas trop comment faire sinon. Ca me limite à une seule implémentation par spécialisation de A mais ça, ça me gène pas.
Si ya un moyen d'avoir Impl hors de A je préférerais, mais si c'est pas possible je ferais avec.

Je me retrouve avec quelques chose comme ça:
Code :
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <tuple>
#include <memory>
 
struct AbsMsg { virtual void foo() { } };
 
template <class T>
struct Msg: public AbsMsg { };
 
template<size_t... Indices>
struct indices {
	typedef indices<Indices..., sizeof...(Indices)> next;
};
 
template<size_t N>
struct build_indices {
	typedef typename build_indices<N - 1>::type::next type;
};
 
template<>
struct build_indices<0> {
	typedef indices<> type;
};
 
template <class... Args>
struct A {
	std::tuple<Args...> m_tuple;
 
	struct Impl;
	std::unique_ptr<Impl> m_impl;
	size_t m_step;
 
	A(Impl *impl): m_impl(impl), m_step(0) { }
	virtual ~A() { }
 
	template <size_t N, class Src>
	void action(Src *sp) {
		typedef Msg<typename std::tuple_element<N, decltype(m_tuple)>::type> Dest;
		Dest *dp = dynamic_cast<Dest*>(sp);
		if(dp) {
			m_impl->foo<N>(dp);
		}
	}
 
	template <size_t N, class Src>
	static void actionWrapper(A<Args...>* _this, Src *sp) {
		_this->action<N, Src>(sp);
	}
 
	template<class Src, size_t... Indices>
	void actionHelper(Src *sp, indices<Indices...>) {
		static void (*lookup[])(A<Args...>*, Src*) = {
			&A::actionWrapper<Indices>...
		};
		lookup[m_step](this, sp);
	}
 
	template <class Src>
	void actionHelper(Src *sp) {
		actionHelper(sp, typename build_indices<std::tuple_size<decltype(m_tuple)>::value>::type()); 
	}
 
};
 
template <>
struct A<int,char>::Impl {
	template <size_t N>
	struct AlwaysFalse {
		enum { value = false };
	};
 
	template <size_t N>
	void foo(Msg<typename std::tuple_element<N, decltype(m_tuple)>::type>* msg) {
		static_assert(AlwaysFalse<N>::value, "please implement");
	}
 
};
 
template<>
void A<int,char>::Impl::foo<0>(Msg<int> *msg) { }
 
template<>
void A<int,char>::Impl::foo<1>(Msg<char> *msg) { }
 
struct B : public A<int, char> {
	B(): A(new A<int, char>::Impl) { }
};
 
 
int main(int argc, char **argv) {
	B b;
	AbsMsg *pm = new Msg<int>();
	AbsMsg *pf = new Msg<float>();
 
	b.actionHelper(pm);
	b.actionHelper(pf);
 
	delete pm;
	delete pf;
 
	return 0;
}
Ca compile sous ICC, mais pas sous MSVC (toujours pas de support des templates variadics...) ni sous gcc (ver: 4.6.2, plus étonnant ça par contre, faut que je le mette à jour pour voir).

Mon code respecte-t-il les standards ?

Les erreurs sous gcc, au cas où ça parlerait à quelqu'un
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
tuple.cpp: In member function ‘void A<Args>::action(Src*) [with unsigned int N = 0u, Src = AbsMsg, Args = {int, char}]:
tuple.cpp:46:3:   instantiated from ‘static void A<Args>::actionWrapper(A<Args>*, Src*) [with unsigned int N = 0u, Src = AbsMsg, Args = {int, char}]’
tuple.cpp:53:3:   instantiated from ‘void A<Args>::actionHelper(Src*, indices<Indices ...>) [with Src = AbsMsg, unsigned int ...Indices = {0u, 1u}, Args = {int, char}]’
tuple.cpp:59:3:   instantiated from ‘void A<Args>::actionHelper(Src*) [with Src = AbsMsg, Args = {int, char}]’
tuple.cpp:94:19:   instantiated from here
tuple.cpp:40:4: error: invalid operands of types ‘<unresolved overloaded function type>’ andunsigned int’ to binary ‘operator<’
 
tuple.cpp: In member function ‘void A<Args>::action(Src*) [with unsigned int N = 1u, Src = AbsMsg, Args = {int, char}]:
tuple.cpp:46:3:   instantiated from ‘static void A<Args>::actionWrapper(A<Args>*, Src*) [with unsigned int N = 1u, Src = AbsMsg, Args = {int, char}]’
tuple.cpp:53:3:   instantiated from ‘void A<Args>::actionHelper(Src*, indices<Indices ...>) [with Src = AbsMsg, unsigned int ...Indices = {0u, 1u}, Args = {int, char}]’
tuple.cpp:59:3:   instantiated from ‘void A<Args>::actionHelper(Src*) [with Src = AbsMsg, Args = {int, char}]’
tuple.cpp:94:19:   instantiated from here
tuple.cpp:40:4: error: invalid operands of types ‘<unresolved overloaded function type>’ andunsigned int’ to binary ‘operator<’
Iradrille est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/12/2012, 13h36   #4
leternel
Expert Confirmé
 
Homme Pierre
Ingénieur développement logiciels
Inscription : juin 2007
Messages : 1 185
Détails du profil
Informations personnelles :
Nom : Homme Pierre
Localisation : France

Informations professionnelles :
Activité : Ingénieur développement logiciels

Informations forums :
Inscription : juin 2007
Messages : 1 185
Points : 2 500
Points : 2 500
essaye d'utiliser le type connu.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
	template <size_t N, class Src>
	static void actionWrapper(A* _this, Src *sp) {
		_this->action<N, Src>(sp);
	}
 
	template<class Src, size_t... Indices>
	void actionHelper(Src *sp, indices<Indices...>) {
		static void (*lookup[])(A*, Src*) = {
			&A::actionWrapper<Indices>...
		};
		lookup[m_step](this, sp);
	}
__________________
Mes principes de bases du codeur qui veut pouvoir dormir:
  • Une variable de moins est une source d'erreur en moins.
  • Un pointeur de moins est une montagne d'erreurs en moins.
  • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
  • La plus sotte des questions est celle qu'on ne pose pas.
leternel est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/12/2012, 17h50   #5
Iradrille
Membre éprouvé
 
Homme
Étudiant
Inscription : juin 2012
Messages : 263
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2012
Messages : 263
Points : 443
Points : 443
Trouvé !

Code :
1
2
3
4
5
6
7
8
9
template <size_t N, class Src>
	void action(Src *sp) {
		typedef Msg<typename std::tuple_element<N, decltype(m_tuple)>::type> Dest;
		Dest *dp = dynamic_cast<Dest*>(sp);
		if(dp) {
			// m_impl->foo<N>(dp);
			m_impl->A::Impl::template  foo<N>(dp);
		}
	}
Fallait avertir le compilo que foo est une fonction template (d'où les erreurs bizarres avec l'opérateur <)

Ca devient obscure le c++ ><
Iradrille est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 02h57.


 
 
 
 
Partenaires

Hébergement Web