Re,
j'ai installé gcc 4.9.1 sur ubuntu mais..., il ne me trouve pas les fonctions std::make_unique, std::make_index_sequence, etc... (Les nouvelles du c++14 quoi)
T'a fait comment pour l'installer ?
Re,
j'ai installé gcc 4.9.1 sur ubuntu mais..., il ne me trouve pas les fonctions std::make_unique, std::make_index_sequence, etc... (Les nouvelles du c++14 quoi)
T'a fait comment pour l'installer ?
Non c'est bon il fallait rajouté l'option -std=c++14.
Bon pas de problème pour les fonctions sans type de retour, mais avec type de retour il me confond les 2 :
Code cpp : 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
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 typedef void DefaultVoid; template<class C, class... ArgT> struct DynamicWrapper { DynamicWrapper(void (C::*pf)(ArgT...)) : pfunc(pf){} template<class O, class... ArgU> void operator()(O* o, ArgU&&... arg) const { if(dynamic_cast<C*>(o)) (dynamic_cast<C*>(o)->*pfunc)(std::forward<ArgU>(arg)...); } private: void (C::*pfunc)(ArgT...); }; template<class F> class DynamicFunction; template<class... ArgT> class DynamicFunction<void(ArgT...)> : std::function<void(ArgT...)> { using Base = std::function<void(ArgT...)>; public: template<class F> DynamicFunction(F&& f) : Base(std::forward<F>(f)) {} template<class C, class... ArgU> DynamicFunction(void (C::*pf)(ArgU...)) : Base(DynamicWrapper<C,ArgU...>(pf)) {} using Base::operator(); }; template<class R, class... ArgT> class DynamicFunction<R(ArgT...)> : std::function<R(ArgT...)> { using Base = std::function<R(ArgT...)>; public: template<class F> DynamicFunction(F&& f) : Base(std::forward<F>(f)) {} template<class C, class... ArgU> DynamicFunction(void (C::*pf)(ArgU...)) : Base(DynamicWrapper<C,ArgU...>(pf)) {} using Base::operator(); }; struct Delegate { Delegate() =default; virtual std::unique_ptr<Delegate> clone() const = 0; virtual void operator()() const = 0; virtual bool hasReturn() const = 0; virtual void* getReturn() const = 0; virtual ~Delegate(); protected: Delegate(const Delegate&){} Delegate& operator=(const Delegate&) { return *this; } }; Delegate::~Delegate(){} template<class... ArgT> struct FastDelegateImpl : Delegate { template<class F, class... ArgU> FastDelegateImpl(F&& f, ArgU&&... arg) : func(std::forward<F>(f)) , param(std::forward<ArgU>(arg)...) {} std::unique_ptr<Delegate> clone() const { return std::make_unique<FastDelegateImpl>(*this); } void operator()() const { call(std::make_index_sequence<sizeof...(ArgT)>()); } template<class... ArgU> void setParam(ArgU&&... arg) { param=std::make_tuple(std::forward<ArgU>(arg)...); } bool hasReturn() const { return false; } void* getReturn() const { return 0; } private: template<std::size_t... I> void call(std::index_sequence<I...>) const { func(std::get<I>(param)...); } DynamicFunction<void(ArgT...)> func; std::tuple<ArgT...> param; }; template<class R, class... ArgT> struct FastDelegateImpl2 : Delegate { template<class F, class... ArgU> FastDelegateImpl2(F&& f, ArgU&&... arg) : func(std::forward<F>(f)) , param(std::forward<ArgU>(arg)...) {} std::unique_ptr<Delegate> clone() const { return std::make_unique<FastDelegateImpl>(*this); } void operator()() const { returnValue = reinterpret_cast<void*>(call(std::make_index_sequence<sizeof...(ArgT)>())); } template<class... ArgU> void setParam(ArgU&&... arg) { param=std::make_tuple(std::forward<ArgU>(arg)...); } bool hasReturn() const { return true; } void* getReturn() const { return returnValue; } private: template<std::size_t... I> void call(std::index_sequence<I...>) const { func(std::get<I>(param)...); } DynamicFunction<R(ArgT...)> func; std::tuple<ArgT...> param; void* returnValue; }; template <typename R> struct FastDelegate { template<class F, class... Arg> FastDelegate(F&& f, Arg&&... arg) : delegate(std::make_unique<FastDelegateImpl2<R, Arg...>> (std::forward<F>(f),std::forward<Arg>(arg)...) ) {} FastDelegate(FastDelegate& rhs) : delegate(rhs.delegate->clone()) {} FastDelegate(const FastDelegate& rhs) : delegate(rhs.delegate->clone()) {} FastDelegate(FastDelegate&& rhs) =default; FastDelegate& operator=(const FastDelegate& rhs) { return operator=(FastDelegate(rhs)); } FastDelegate& operator=(FastDelegate&&) =default; R operator()() const { (*delegate)(); void* p = delegate->getReturn(); return *reinterpret_cast<R*> (&p); } template<class... Arg> void setParams(Arg&&... arg) { using DynamicType = FastDelegateImpl2<Arg...>*; if(dynamic_cast<DynamicType>(delegate.get())) dynamic_cast<DynamicType>(delegate.get())->setParam(std::forward<Arg>(arg)...); } void boo(){} private: std::unique_ptr<Delegate> delegate; }; template <> struct FastDelegate <DefaultVoid> { template<class F, class... Arg> FastDelegate(F&& f, Arg&&... arg) : delegate(std::make_unique<FastDelegateImpl<Arg...>> (std::forward<F>(f),std::forward<Arg>(arg)...) ) {} FastDelegate(FastDelegate& rhs) : delegate(rhs.delegate->clone()) {} FastDelegate(const FastDelegate& rhs) : delegate(rhs.delegate->clone()) {} FastDelegate(FastDelegate&& rhs) =default; FastDelegate& operator=(const FastDelegate& rhs) { return operator=(FastDelegate(rhs)); } FastDelegate& operator=(FastDelegate&&) =default; void operator()() const { (*delegate)(); } template<class... Arg> void setParams(Arg&&... arg) { using DynamicType = FastDelegateImpl<Arg...>*; if(dynamic_cast<DynamicType>(delegate.get())) dynamic_cast<DynamicType>(delegate.get())->setParam(std::forward<Arg>(arg)...); } void boo(){} private: std::unique_ptr<Delegate> delegate;
Il me prend void pour R, dans FastDelegateImpl2. (Donc il choisi la version avec retour même si la fonction n'a pas de retour)
Essaie de définir le cas particulier (void) comme spécialisation de la template du cas général.
Il faut dans ce cas que le cas void soit déclaré (et défini, donc) après le cas général.
Mes principes de bases du codeur qui veut pouvoir dormir:Pour faire des graphes, essayez yEd.
- 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.
- jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
- La plus sotte des questions est celle qu'on ne pose pas.
le ter nel est le titre porté par un de mes personnages de jeu de rôle
Ok, je vais essayer ça.
Salut!
Le fait que je n'ai pas utilisé de wrapper sur un std::function c'est aussi pour cette raison.
Ce code-ci est très intéressant.
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 void bar(const char* str, const char* str2) { std::cout<<"bar : "<<str<<" "<<str2<<std::endl; } int main(int argv, char* argc[]) { auto function = std::bind(&bar, "1", _1); using T = decltype(std::bind(&bar, "1", _1)); odfaeg::FastDelegate<void> freeFuncDelegate(function, "1", _1); freeFuncDelegate.setParams<T>("2"); freeFuncDelegate(); }
Que se passerait t'il dans le cas ou l'objet passé au delegate n'est pas de type std::function ce qui est le cas ici.
Bref, je veux pas qu'un bête wrapper sur un std::function mais sur n'importe quel type d'objet "callable".
Au cas ou par exemple je ne connais pas la valeur d'un paramètre lors de la déclaration du delegate, je n'ai qu'à passer un std::bind est le tout est joué.
Ce code a surtout aucun sens, pourquoi :
? Ton function est un callable a un seul paramètre, pourquoi tu lui en passes deux, qui plus est avec un placeholder alors que le code actuel ne gère pas les placeholder (comme il ne gère pas les std::ref) ? D'ailleurs pour les gérer (les deux) je n'ai pas encore réfléchie à la question, mais je vois venir un nouveau type-erasure à utiliser comme type dans le tuple (l'aternative étant de retourner un nouvel objet à chaque setParam à priori).
Code : Sélectionner tout - Visualiser dans une fenêtre à part odfaeg::FastDelegate<void> freeFuncDelegate(function, "1", _1);
Dans l'absolue std::bind retourne une instance d'une classe inconnue qui surcharge l'opérateur operator() exactement comme le type d'une lambda. std::function est un type-erasure sur n'importe quel callable, donc ton wrapper gère n'importe quel callable dans l'absolu.
Le code de retour je ne l'ai pas géré, mais tu l'avais fais sur ton ancien code et tu peux appliquer la même technique (i.e. une spécialisation complète de la classe) ou bien essayer de factorier un peu pour ne pas doubler la taille du code alors qu'il n'y a que quelques éléments qui change (à coup de decltype, declval et enable_if).
Je vais essayer de t'expliquer en fait :
J'ai rajouté un paramètre à la fonction :
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 void bar(const char* str, const char* str2) { std::cout<<"bar : "<<str<<" "<<str2<<std::endl; }
Donc elle en a deux maintenant.
Ensuite si je veux faire ceci dans le main :
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 int main(int argv, char* argc[]) { auto function = std::bind(&bar, "1", _1); odfaeg::FastDelegate<void> freeFuncDelegate(function, "1", _1); fonction(function, freeFuncDelegate); }
Et ceci ailleurs que dans le main (par exemple dans une autre fonction)
Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 template <typename T> void fonction (typename T type, FastDelegate<void> delegate) { delegate.setParams<T>("2"); delegate(); }
std::function ne peut pas enregistrer une fonction avec un placeholder vu que les fonctions avec les placeholders ne sont pas "callable".
L'idée est de faire un tableau sur pointeurs de fonctions non callable, je vais devoir me débrouiller par contre pour enregistrer le type de std::bind, c'est à dire le type de T dans mon cas. (mais ça pas de soucis j'ai une factory donc j'ai ma petite idée en comparent les types à l'exécution)
Et je passe les paramètres au delegate avant d'appeler la fonction pour avoir une fonction "callable" et ensuite appeler l'operateur() de std::bind!
Car le problème de std::bind c'est qu'il n'est pas très modulable. :/
J'ai très bien compris la première fois et non ca n'a toujours aucun sens d'écrire ce que tu as écris.
Un placeholder ce n'est pas anodin a traiter, si tu ne fais rien pour et qu'il n'est pas dans un std::bind alors c'est assez peu probable que ca marche. Ensuite function est un foncteur à un paramètre, FastDelegate enregistre un foncteur accompagné de ses paramères dans un tuple, un seul paramètre donc un seul élément à passer. D'où la conclusion : ton code ne veut rien dire.
Là ca a du sens.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 odfaeg::FastDelegate<void> freeFuncDelegate(function, "1"); freeFuncDelegate();
Pour ta fonction fonction : le code de setParam est, actuellement, fait pour profiter de la déduction automatique des paramètres template, c'est dans la grande majorité des cas inutile de les indiquer. Ensuite sur le fond, quel est l'intérêt de FastDelegate si tu dois aussi donner function en paramètre ? L'intérêt d'un type-erasure c'est de s'abstraire, partiellement, du type, si tu dois repasser l'objet d'origine pour récupérer le type initial, l'intérêt devient presque nul.
std::bind tiend parfaitement son rôle, même si aujourd'hui son intérêt est plus limité grâce aux lambda. Je ne vois pas ce que tu veux lui ajouter comme modularité : l'objectif est de fixer partiellement les paramètres d'un foncteur, il y arrive, rien à rajouter. L'objectif final de ta classe, si j'ai bien compris, c'est d'avoir associer un foncteur et ses paramètres de manière à pouvoir les faire varier. A l'heure actuelle tu gères le cas : d'un retour void, en fixant l'ensemble des paramètres, sans passage par référence et en devant indiquer tout les paramètres à fixer en même temps. Ca fait beaucoup de point à travailler pour arriver au résultat final, par contre niveau foncteur accepté, tu peux tout prendre, que ca vienne de std::bind ou d'autre chose grâce à l'utilisation de std::function.
Si tu veux améliorer ces points, dans l'ordre je dirais :
- Prendre en charge le type de retour
- Permettre de ne changer qu'un paramètre
- Prendre en charge le passage par référence
- Prendre en charge les placeholder et une fixation partielle des paramètres
Le dernier point est probablement le plus difficile et risque de demander un réorganisation d'une partie d'un code. Les deuxième est surment le plus simple à faire.
Ouais ce sont les deux derniers points pour lesquels je sèche. :/
Salut,
Flob90, je ne sais pas du tout comment ton code arrive à compiler, chez moi, j'ai plein d'undefined reference errors pour le dynamic cast et quand je veux passer des const char* aux fonctions (à la place des int) ça ne compile pas.
Tu peux donner les erreurs complètes ?
C'est bien ce code là non ?
Code cpp : 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
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 typedef void DefaultVoid; template<class C, class... ArgT> struct DynamicWrapper { DynamicWrapper(void (C::*pf)(ArgT...)) : pfunc(pf){} template<class O, class... ArgU> void operator()(O* o, ArgU&&... arg) const { if(dynamic_cast<C*>(o)) (dynamic_cast<C*>(o)->*pfunc)(std::forward<ArgU>(arg)...); } private: void (C::*pfunc)(ArgT...); }; template<class F> class DynamicFunction; template<class... ArgT> class DynamicFunction<void(ArgT...)> : std::function<void(ArgT...)> { using Base = std::function<void(ArgT...)>; public: template<class F> DynamicFunction(F&& f) : Base(std::forward<F>(f)) {} template<class C, class... ArgU> DynamicFunction(void (C::*pf)(ArgU...)) : Base(DynamicWrapper<C,ArgU...>(pf)) {} using Base::operator(); }; template<class R, class... ArgT> class DynamicFunction<R(ArgT...)> : std::function<R(ArgT...)> { using Base = std::function<R(ArgT...)>; public: template<class F> DynamicFunction(F&& f) : Base(std::forward<F>(f)) {} template<class C, class... ArgU> DynamicFunction(void (C::*pf)(ArgU...)) : Base(DynamicWrapper<C,ArgU...>(pf)) {} using Base::operator(); }; struct Delegate { Delegate(){} virtual std::unique_ptr<Delegate> clone() const = 0; virtual void operator()(); virtual bool hasReturn() const = 0; virtual void* getReturn() const = 0; virtual ~Delegate() {} protected: Delegate(const Delegate&){} Delegate& operator=(const Delegate&) { return *this; } }; template<class... ArgT> struct FastDelegateImpl : Delegate { template<class F, class... ArgU> FastDelegateImpl(F&& f, ArgU&&... arg) : Delegate() , func(std::forward<F>(f)) , param(std::forward<ArgU>(arg)...) {} std::unique_ptr<Delegate> clone() const { return std::make_unique<FastDelegateImpl>(*this); } void operator()() { call(std::make_index_sequence<sizeof...(ArgT)>()); } template<class... ArgU> void setParam(ArgU&&... arg) { param=std::make_tuple(std::forward<ArgU>(arg)...); } bool hasReturn() const { return false; } void* getReturn() const { return 0; } private: template<std::size_t... I> void call(std::index_sequence<I...>) const { func(std::get<I>(param)...); } DynamicFunction<void(ArgT...)> func; std::tuple<ArgT...> param; }; template<class R, class... ArgT> struct FastDelegateImpl2 : Delegate { template<class F, class... ArgU> FastDelegateImpl2(F&& f, ArgU&&... arg) : func(std::forward<F>(f)) , param(std::forward<ArgU>(arg)...) {} std::unique_ptr<Delegate> clone() const { return std::make_unique<FastDelegateImpl2>(*this); } void operator()() { returnValue = reinterpret_cast<void*>(call(std::make_index_sequence<sizeof...(ArgT)>())); } template<class... ArgU> void setParam(ArgU&&... arg) { param=std::make_tuple(std::forward<ArgU>(arg)...); } bool hasReturn() const { return true; } void* getReturn() const { return returnValue; } private: template<std::size_t... I> R call(std::index_sequence<I...>) { return func(std::get<I>(param)...); } DynamicFunction<R(ArgT...)> func; std::tuple<ArgT...> param; void* returnValue; }; template <typename R> struct FastDelegate { template<class F, class... Arg> FastDelegate(F&& f, Arg&&... arg) : delegate(std::make_unique<FastDelegateImpl2<R, Arg...>> (std::forward<F>(f),std::forward<Arg>(arg)...) ) {} FastDelegate(FastDelegate& rhs) : delegate(rhs.delegate->clone()) {} FastDelegate(const FastDelegate& rhs) : delegate(rhs.delegate->clone()) {} FastDelegate(FastDelegate&& rhs) =default; FastDelegate& operator=(const FastDelegate& rhs) { return operator=(FastDelegate(rhs)); } FastDelegate& operator=(FastDelegate&&) =default; R operator()() const { (*delegate)(); void* p = delegate->getReturn(); return *reinterpret_cast<R*> (&p); } template<class... Arg> void setParams(Arg&&... arg) { using DynamicType = FastDelegateImpl2<Arg...>*; if(dynamic_cast<DynamicType>(delegate.get())) dynamic_cast<DynamicType>(delegate.get())->setParam(std::forward<Arg>(arg)...); } void boo(){} private: std::unique_ptr<Delegate> delegate; }; template <> struct FastDelegate <DefaultVoid> { template<class F, class... Arg> FastDelegate(F&& f, Arg&&... arg) : delegate(std::make_unique<FastDelegateImpl<Arg...>> (std::forward<F>(f),std::forward<Arg>(arg)...) ) {} FastDelegate(FastDelegate& rhs) : delegate(rhs.delegate->clone()) {} FastDelegate(const FastDelegate& rhs) : delegate(rhs.delegate->clone()) {} FastDelegate(FastDelegate&& rhs) =default; FastDelegate& operator=(const FastDelegate& rhs) { return operator=(FastDelegate(rhs)); } FastDelegate& operator=(FastDelegate&&) =default; void operator()() const { (*delegate)(); } template<class... Arg> void setParams(Arg&&... arg) { using DynamicType = FastDelegateImpl<Arg...>*; if(dynamic_cast<DynamicType>(delegate.get())) dynamic_cast<DynamicType>(delegate.get())->setParam(std::forward<Arg>(arg)...); } void boo(){} private: std::unique_ptr<Delegate> delegate; };
J'ai juste rajouté la spécialisation pour les fonctions avec type de retour.
Bref voici les erreurs :
Et le main :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 ||=== Build: Debug in ODFAEG-DEMO (compiler: GNU GCC Compiler) ===| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp||In function int main(int, char**):| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|525|référence indéfinie vers « vtable for odfaeg::Delegate »| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|530|référence indéfinie vers « vtable for odfaeg::Delegate »| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|532|référence indéfinie vers « vtable for odfaeg::Delegate »| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|651|référence indéfinie vers « typeinfo for odfaeg::Delegate »| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|652|référence indéfinie vers « typeinfo for odfaeg::Delegate »| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|651|référence indéfinie vers « typeinfo for odfaeg::Delegate »| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|652|référence indéfinie vers « typeinfo for odfaeg::Delegate »| ||=== Build failed: 7 error(s), 1 warning(s) (0 minute(s), 1 second(s)) ===|
Code cpp : 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
31
32
33
34
35
36
37
38
39
40 class Bar { public : void foo (int str) { std::cout<<"foo : "<<str<<std::endl; } int rfoo(int str) { std::cout<<"bar : "<<str<<std::endl; return 10; } virtual ~Bar() { } }; void bar(int str) { std::cout<<"bar : "<<str<<std::endl; } int rbar(int str) { std::cout<<"bar : "<<str<<std::endl; return 10; } int main(int argv, char* argc[]) { odfaeg::FastDelegate<void> freeFuncDelegate(&bar, 1); freeFuncDelegate.setParams(2); freeFuncDelegate(); Bar b; Bar* f = new Foo(); odfaeg::FastDelegate<void> memberFuncDelegate(&Bar::foo, &b, 3); memberFuncDelegate.setParams(&b, 4); memberFuncDelegate(); odfaeg::FastDelegate<void> anonymousFunction([](int arg){std::cout<<"anonymous : "<<arg<<std::endl;}, 5); anonymousFunction.setParams(6); anonymousFunction(); odfaeg::FastDelegate<int> rfreeFuncDelegate(&rbar, 7); odfaeg::FastDelegate<int> rmemberFuncDelegate(&Bar::rfoo, &b, 8); const int r1 = rfreeFuncDelegate(); std::cout<<"r1 : "<<r1<<std::endl; const int r2 = rmemberFuncDelegate(); std::cout<<"r2 : "<<r2<<std::endl; return 0; }
J'ai bien mit le code dans un projet à part.
Avant de rajouter et modifier ce que j'ai écrit, as-tu essayé en copiant/collant simplement le code ?
Les fonctions définient à l'extérieur du corps de la classe c'est pas anodin.
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
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 namespace odfaeg { template<class C, class... ArgT> struct DynamicWrapper { DynamicWrapper(void (C::*pf)(ArgT...)) : pfunc(pf){} template<class O, class... ArgU> void operator()(O* o, ArgU&&... arg) const { if(dynamic_cast<C*>(o)) (dynamic_cast<C*>(o)->*pfunc)(std::forward<ArgU>(arg)...); } private: void (C::*pfunc)(ArgT...); }; template<class F> class DynamicFunction; template<class... ArgT> class DynamicFunction<void(ArgT...)> : std::function<void(ArgT...)> { using Base = std::function<void(ArgT...)>; public: template<class F> DynamicFunction(F&& f) : Base(std::forward<F>(f)) {} template<class C, class... ArgU> DynamicFunction(void (C::*pf)(ArgU...)) : Base(DynamicWrapper<C,ArgU...>(pf)) {} using Base::operator(); }; struct Delegate { Delegate() =default; virtual std::unique_ptr<Delegate> clone() const = 0; virtual void operator()() const = 0; virtual ~Delegate(); protected: Delegate(const Delegate&){} Delegate& operator=(const Delegate&) { return *this; } }; Delegate::~Delegate(){} template<class... ArgT> struct FastDelegateImpl : Delegate { template<class F, class... ArgU> FastDelegateImpl(F&& f, ArgU&&... arg) : func(std::forward<F>(f)) , param(std::forward<ArgU>(arg)...) {} std::unique_ptr<Delegate> clone() const { return std::make_unique<FastDelegateImpl>(*this); } void operator()() const { call(std::make_index_sequence<sizeof...(ArgT)>()); } template<class... ArgU> void setParam(ArgU&&... arg) { param=std::make_tuple(std::forward<ArgU>(arg)...); } private: template<std::size_t... I> void call(std::index_sequence<I...>) const { func(std::get<I>(param)...); } DynamicFunction<void(ArgT...)> func; std::tuple<ArgT...> param; }; struct FastDelegate { template<class F, class... Arg> FastDelegate(F&& f, Arg&&... arg) : delegate(std::make_unique<FastDelegateImpl<Arg...>> (std::forward<F>(f),std::forward<Arg>(arg)...) ) {} FastDelegate(FastDelegate& rhs) : delegate(rhs.delegate->clone()) {} FastDelegate(const FastDelegate& rhs) : delegate(rhs.delegate->clone()) {} FastDelegate(FastDelegate&& rhs) =default; FastDelegate& operator=(const FastDelegate& rhs) { return operator=(FastDelegate(rhs)); } FastDelegate& operator=(FastDelegate&&) =default; void operator()() const { (*delegate)(); } template<class... Arg> void setParam(Arg&&... arg) { using DynamicType = FastDelegateImpl<Arg...>*; if(dynamic_cast<DynamicType>(delegate.get())) dynamic_cast<DynamicType>(delegate.get())->setParam(std::forward<Arg>(arg)...); } void boo(){} private: std::unique_ptr<Delegate> delegate; }; } void foo(int i, int j) { std::cout << i << j; } struct A { void bar(int i) { std::cout << i; } }; struct B { virtual void foo() { std::cout << 1; } virtual ~B(); }; B::~B(){} struct C : B { void foo(); }; void C::foo(){ std::cout << 2; } int main(){ odfaeg::FastDelegate f1(foo,3,4); f1(); f1.setParam(5,6); f1(); std::cout << std::endl; odfaeg::FastDelegate f2( [](int i, int j){ std::cout << i << j; }, 7,8 ); f2(); f2.setParam(9,10); f2(); std::cout << std::endl; int i = 11; odfaeg::FastDelegate f3( [i](int j){ std::cout << i << j; }, 12 ); f3(); f3.setParam(13); f3(); std::cout << std::endl; A a; odfaeg::FastDelegate f4(&A::bar,&a,14); f4(); f4.setParam(&a,15); f4(); std::cout << std::endl; odfaeg::FastDelegate f5 = f1; f5(); f5=f3; f5(); std::cout << std::endl; C c; B* b = &c; odfaeg::FastDelegate f6(&C::foo,b); f6(); f6.setParam(&c); f6(); std::cout << std::endl; }
PS: Il manque juste les include.
Il manque D dans ton code.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|69|error: D was not declared in this scope|
Voila, code édité, plus besoin de D. (C'était le dernier exemple que j'avais ajouter en éditant le message où il y a le code, il est pas particulièrement pertinant).
Bon j'ai commenté celui qui utilise la classe D, et ça compile et ça s'exécute sans problème, maintenant, il faut que je voie comment faire ça pour le types de retour.
Ha oui tu défini le destructeur virtuel en dehors de la classe c'est pour ça.
Sinon ça ne marche qu'avec des int, ça ne fonctionne pas avec des std::string. (Ni des const char*)
PS : hors que ma version fonctionne avec les const char*.
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
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 ||=== Build: Debug in ODFAEG-DEMO (compiler: GNU GCC Compiler) ===| /usr/include/c++/4.9/tuple||In instantiation of std::_Tuple_impl<_Idx, _Head, _Tail ...>& std::_Tuple_impl<_Idx, _Head, _Tail ...>::operator=(std::_Tuple_impl<_Idx, _UHead, _UTails ...>&&) [with _UHead = const char*; _UTails = {const char*}; long unsigned int _Idx = 0ul; _Head = const char (&)[2]; _Tail = {const char (&)[2]}]:| /usr/include/c++/4.9/tuple|642|required from std::tuple<_T1, _T2>& std::tuple<_T1, _T2>::operator=(std::tuple<_U1, _U2>&&) [with _U1 = const char*; _U2 = const char*; _T1 = const char (&)[2]; _T2 = const char (&)[2]]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|532|required from void odfaeg::FastDelegateImpl<ArgT>::setParam(ArgU&& ...) [with ArgU = {const char (&)[2], const char (&)[2]}; ArgT = {const char (&)[2], const char (&)[2]}]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|566|required from void odfaeg::FastDelegate::setParam(Arg&& ...) [with Arg = {const char (&)[2], const char (&)[2]}]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|25|required from here| /usr/include/c++/4.9/tuple|366|error: assignment of read-only location std::_Tuple_impl<_Idx, _Head, _Tail ...>::_M_head<0ul, const char (&)[2], {const char (&)[2]}>((*(std::_Tuple_impl<0ul, const char (&)[2], const char (&)[2]>*)this))| /usr/include/c++/4.9/tuple|366|error: incompatible types in assignment of const char* to const char [2]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h||In instantiation of odfaeg::DynamicFunction<void(ArgT ...)>::DynamicFunction(F&&) [with F = main()::<lambda(std::string&, std::string&)>; ArgT = {const char (&)[2], const char (&)[2]}]:| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|524|required from odfaeg::FastDelegateImpl<ArgT>::FastDelegateImpl(F&&, ArgU&& ...) [with F = main()::<lambda(std::string&, std::string&)>; ArgU = {const char (&)[2], const char (&)[2]}; ArgT = {const char (&)[2], const char (&)[2]}]| /usr/include/c++/4.9/bits/unique_ptr.h|762|required from typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = odfaeg::FastDelegateImpl<const char (&)[2], const char (&)[2]>; _Args = {main()::<lambda(std::string&, std::string&)>, const char (&)[2], const char (&)[2]}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<odfaeg::FastDelegateImpl<const char (&)[2], const char (&)[2]>, std::default_delete<odfaeg::FastDelegateImpl<const char (&)[2], const char (&)[2]> > >]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|547|required from odfaeg::FastDelegate::FastDelegate(F&&, Arg&& ...) [with F = main()::<lambda(std::string&, std::string&)>; Arg = {const char (&)[2], const char (&)[2]}]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|32|required from here| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|496|error: no matching function for call to std::function<void(const char (&)[2], const char (&)[2])>::function(main()::<lambda(std::string&, std::string&)>)| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|496|note: candidates are:| /usr/include/c++/4.9/functional|2226|note: template<class _Functor, class> std::function<_Res(_ArgTypes ...)>::function(_Functor)| /usr/include/c++/4.9/functional|2226|note: template argument deduction/substitution failed:| /usr/include/c++/4.9/functional|2201|note: std::function<_Res(_ArgTypes ...)>::function(std::function<_Res(_ArgTypes ...)>&&) [with _Res = void; _ArgTypes = {const char (&)[2], const char (&)[2]}]| /usr/include/c++/4.9/functional|2201|note: no known conversion for argument 1 from main()::<lambda(std::string&, std::string&)> to std::function<void(const char (&)[2], const char (&)[2])>&&| /usr/include/c++/4.9/functional|2404|note: std::function<_Res(_ArgTypes ...)>::function(const std::function<_Res(_ArgTypes ...)>&) [with _Res = void; _ArgTypes = {const char (&)[2], const char (&)[2]}]| /usr/include/c++/4.9/functional|2404|note: no known conversion for argument 1 from main()::<lambda(std::string&, std::string&)> to const std::function<void(const char (&)[2], const char (&)[2])>&| /usr/include/c++/4.9/functional|2181|note: std::function<_Res(_ArgTypes ...)>::function(std::nullptr_t) [with _Res = void; _ArgTypes = {const char (&)[2], const char (&)[2]}; std::nullptr_t = std::nullptr_t]| /usr/include/c++/4.9/functional|2181|note: no known conversion for argument 1 from main()::<lambda(std::string&, std::string&)> to std::nullptr_t| /usr/include/c++/4.9/functional|2174|note: std::function<_Res(_ArgTypes ...)>::function() [with _Res = void; _ArgTypes = {const char (&)[2], const char (&)[2]}]| /usr/include/c++/4.9/functional|2174|note: candidate expects 0 arguments, 1 provided| /usr/include/c++/4.9/tuple||In instantiation of std::_Tuple_impl<_Idx, _Head, _Tail ...>& std::_Tuple_impl<_Idx, _Head, _Tail ...>::operator=(std::_Tuple_impl<_Idx, _UHead, _UTails ...>&&) [with _UHead = const char*; _UTails = {const char*}; long unsigned int _Idx = 0ul; _Head = const char (&)[2]; _Tail = {const char (&)[3]}]:| /usr/include/c++/4.9/tuple|642|required from std::tuple<_T1, _T2>& std::tuple<_T1, _T2>::operator=(std::tuple<_U1, _U2>&&) [with _U1 = const char*; _U2 = const char*; _T1 = const char (&)[2]; _T2 = const char (&)[3]]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|532|required from void odfaeg::FastDelegateImpl<ArgT>::setParam(ArgU&& ...) [with ArgU = {const char (&)[2], const char (&)[3]}; ArgT = {const char (&)[2], const char (&)[3]}]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|566|required from void odfaeg::FastDelegate::setParam(Arg&& ...) [with Arg = {const char (&)[2], const char (&)[3]}]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|34|required from here| /usr/include/c++/4.9/tuple|366|error: assignment of read-only location std::_Tuple_impl<_Idx, _Head, _Tail ...>::_M_head<0ul, const char (&)[2], {const char (&)[3]}>((*(std::_Tuple_impl<0ul, const char (&)[2], const char (&)[3]>*)this))| /usr/include/c++/4.9/tuple|366|error: incompatible types in assignment of const char* to const char [2]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h||In instantiation of odfaeg::DynamicFunction<void(ArgT ...)>::DynamicFunction(F&&) [with F = main()::<lambda(int)>; ArgT = {const char (&)[3]}]:| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|524|required from odfaeg::FastDelegateImpl<ArgT>::FastDelegateImpl(F&&, ArgU&& ...) [with F = main()::<lambda(int)>; ArgU = {const char (&)[3]}; ArgT = {const char (&)[3]}]| /usr/include/c++/4.9/bits/unique_ptr.h|762|required from typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = odfaeg::FastDelegateImpl<const char (&)[3]>; _Args = {main()::<lambda(int)>, const char (&)[3]}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<odfaeg::FastDelegateImpl<const char (&)[3]>, std::default_delete<odfaeg::FastDelegateImpl<const char (&)[3]> > >]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|547|required from odfaeg::FastDelegate::FastDelegate(F&&, Arg&& ...) [with F = main()::<lambda(int)>; Arg = {const char (&)[3]}]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|42|required from here| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|496|error: no matching function for call to std::function<void(const char (&)[3])>::function(main()::<lambda(int)>)| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|496|note: candidates are:| /usr/include/c++/4.9/functional|2226|note: template<class _Functor, class> std::function<_Res(_ArgTypes ...)>::function(_Functor)| /usr/include/c++/4.9/functional|2226|note: template argument deduction/substitution failed:| /usr/include/c++/4.9/functional|2201|note: std::function<_Res(_ArgTypes ...)>::function(std::function<_Res(_ArgTypes ...)>&&) [with _Res = void; _ArgTypes = {const char (&)[3]}]| /usr/include/c++/4.9/functional|2201|note: no known conversion for argument 1 from main()::<lambda(int)> to std::function<void(const char (&)[3])>&&| /usr/include/c++/4.9/functional|2404|note: std::function<_Res(_ArgTypes ...)>::function(const std::function<_Res(_ArgTypes ...)>&) [with _Res = void; _ArgTypes = {const char (&)[3]}]| /usr/include/c++/4.9/functional|2404|note: no known conversion for argument 1 from main()::<lambda(int)> to const std::function<void(const char (&)[3])>&| /usr/include/c++/4.9/functional|2181|note: std::function<_Res(_ArgTypes ...)>::function(std::nullptr_t) [with _Res = void; _ArgTypes = {const char (&)[3]}; std::nullptr_t = std::nullptr_t]| /usr/include/c++/4.9/functional|2181|note: no known conversion for argument 1 from main()::<lambda(int)> to std::nullptr_t| /usr/include/c++/4.9/functional|2174|note: std::function<_Res(_ArgTypes ...)>::function() [with _Res = void; _ArgTypes = {const char (&)[3]}]| /usr/include/c++/4.9/functional|2174|note: candidate expects 0 arguments, 1 provided| /usr/include/c++/4.9/tuple||In instantiation of std::_Tuple_impl<_Idx, _Head, _Tail ...>& std::_Tuple_impl<_Idx, _Head, _Tail ...>::operator=(std::_Tuple_impl<_Idx, _UHead, _UTails ...>&&) [with _UHead = const char*; _UTails = {}; long unsigned int _Idx = 0ul; _Head = const char (&)[3]; _Tail = {}]:| /usr/include/c++/4.9/tuple|500|required from std::tuple< <template-parameter-1-1> >& std::tuple< <template-parameter-1-1> >::operator=(std::tuple<_Args1 ...>&&) [with _UElements = {const char*}; <template-parameter-2-2> = void; _Elements = {const char (&)[3]}]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|532|required from void odfaeg::FastDelegateImpl<ArgT>::setParam(ArgU&& ...) [with ArgU = {const char (&)[3]}; ArgT = {const char (&)[3]}]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/delegate.h|566|required from void odfaeg::FastDelegate::setParam(Arg&& ...) [with Arg = {const char (&)[3]}]| /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|44|required from here| /usr/include/c++/4.9/tuple|366|error: assignment of read-only location std::_Tuple_impl<_Idx, _Head, _Tail ...>::_M_head<0ul, const char (&)[3], {}>((*(std::_Tuple_impl<0ul, const char (&)[3]>*)this))| /usr/include/c++/4.9/tuple|366|error: incompatible types in assignment of const char* to const char [3]| ||=== Build failed: 8 error(s), 25 warning(s) (0 minute(s), 0 second(s)) ===|
Dernière modification par Invité ; 05/09/2014 à 14h02.
D'accord, là c'est un vrai problème. On doit pouvoir le résoudre en parti avec une decay conversion où il faut (je suis pas chez moi, je peux pas me plonger assez dans le code pour te dire où exactement). En attendant tu peux déjà avancer sur les autres problématique avec cette base.
Edit: Quand tu postes une erreur, c'est mieux avec le code correspondant quand même.
Je ne peux pas trop dire ou non plus au niveau du std::decay.
Je m'y connais très peu en c++11 et la méta-programmation me cassais tellement le crâne à certains moment que comme tu as pu le voir j'ai fais une solution à l'ancienne sans passer par un std::function, ni par des std::decay, des std::forward et tout le bazard. (A cause justement de tout ses problèmes)
Et encore, ma solution ne fonctionne pas avec les références.
Utilisation :
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
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130 #include<functional> #include<memory> #include<tuple> #include<type_traits> #include<utility> #include<boost/mpl/apply.hpp> #include<boost/mpl/if.hpp> #include<boost/mpl/placeholders.hpp> namespace mpl = boost::mpl; using mpl::placeholders::_; namespace odfaeg { template<class C, class R, class... ArgT> struct DynamicWrapper { DynamicWrapper(R (C::*pf)(ArgT...)) : pfunc(pf) {} template<class O, class... ArgU> R operator()(O* o, ArgU&&... arg) const { if(dynamic_cast<C*>(o)) return (dynamic_cast<C*>(o)->*pfunc)(std::forward<ArgU>(arg)...); } private: R (C::*pfunc)(ArgT...); }; template<class F> class DynamicFunction; template<class R, class... ArgT> class DynamicFunction<R(ArgT...)> : std::function<R(ArgT...)> { using Base = std::function<R(ArgT...)>; public: template<class F> DynamicFunction(F&& f) : Base(std::forward<F>(f)) {} template<class C, class... ArgU> DynamicFunction(R (C::*pf)(ArgU...)) : Base(DynamicWrapper<C,R,ArgU...>(pf)) {} using Base::operator(); }; template<class R> struct Delegate { Delegate() =default; virtual std::unique_ptr<Delegate> clone() const = 0; virtual R operator()() const = 0; virtual ~Delegate(){} protected: Delegate(const Delegate&){} Delegate& operator=(const Delegate&) { return *this; } }; template<class PFun, class PConv, class R, class... ArgT> struct FastDelegateImpl : Delegate<R> { template<class F, class... ArgU> FastDelegateImpl(F&& f, ArgU&&... arg) : func(std::forward<F>(f)) , param(std::forward<ArgU>(arg)...) {} std::unique_ptr<Delegate<R>> clone() const { return std::make_unique<FastDelegateImpl>(*this); } R operator()() const { return call(std::make_index_sequence<sizeof...(ArgT)>()); } template<class... ArgU> void setParam(ArgU&&... arg) { param=std::make_tuple(std::forward<ArgU>(arg)...); } private: template<std::size_t... I> R call(std::index_sequence<I...>) const { return func(std::get<I>(param)...); } typename mpl::apply< PFun,R(typename mpl::apply<PConv,ArgT>::type...) >::type func; std::tuple<typename mpl::apply<PConv,ArgT>::type...> param; }; template< class R, class PFun =DynamicFunction<_>, class PConv =mpl::if_<std::is_same<std::decay<_>,const char*>,std::string,std::decay<_>> > struct FastDelegate { template<class F, class... Arg> FastDelegate(F&& f, Arg&&... arg) : delegate(std::make_unique<FastDelegateImpl<PFun,PConv,R,Arg...>> (std::forward<F>(f),std::forward<Arg>(arg)...) ) {} FastDelegate(FastDelegate& rhs) : delegate(rhs.delegate->clone()) {} FastDelegate(const FastDelegate& rhs) : delegate(rhs.delegate->clone()) {} FastDelegate(FastDelegate&& rhs) =default; FastDelegate& operator=(const FastDelegate& rhs) { return operator=(FastDelegate(rhs)); } FastDelegate& operator=(FastDelegate&&) =default; R operator()() const { return (*delegate)(); } template<class... Arg> void setParam(Arg&&... arg) { using DynamicType = FastDelegateImpl<PFun,PConv,R,Arg...>*; if(dynamic_cast<DynamicType>(delegate.get())) dynamic_cast<DynamicType>(delegate.get())->setParam(std::forward<Arg>(arg)...); } private: std::unique_ptr<Delegate<R>> delegate; }; }
Code de retour, classe de politique (nécessite boost.mpl) et std::string dans une certaine mesure. Gérer les cas comme :
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
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
102
103
104
105
106
107
108 #include<iostream> #include<string> using namespace std::literals; void foo(int i, int j) { std::cout << i << j; } struct A { void foo(int i) { std::cout << i; } }; struct B { virtual void foo() { std::cout << 1; } virtual ~B(); }; B::~B(){} struct C : B { void foo(); }; void C::foo(){ std::cout << 2; } struct D { void operator()(int i) const { std::cout << i; } }; void bar(const std::string& s) { std::cout << s; } int goo(int i) { return i; } int main(){ odfaeg::FastDelegate<void> f1(foo,3,4); f1(); f1.setParam(5,6); f1(); std::cout << std::endl; odfaeg::FastDelegate<void> f2( [](int i, int j){ std::cout << i << j; }, 7,8 ); f2(); f2.setParam(9,10); f2(); std::cout << std::endl; int i = 11; odfaeg::FastDelegate<void> f3( [i](int j){ std::cout << i << j; }, 12 ); f3(); f3.setParam(13); f3(); std::cout << std::endl; A a; odfaeg::FastDelegate<void> f4(&A::foo,&a,14); f4(); f4.setParam(&a,15); f4(); std::cout << std::endl; odfaeg::FastDelegate<void> f5 = f1; f5(); f5=f3; f5(); std::cout << std::endl; C c; B* b = &c; odfaeg::FastDelegate<void> f6(&C::foo,b); f6(); f6.setParam(&c); f6(); std::cout << std::endl; odfaeg::FastDelegate<void> f7(D(),16); f7(); f7.setParam(17); f7(); std::cout << std::endl; odfaeg::FastDelegate<void> f8(bar,"ab"s); f8(); f8.setParam("abc"s); f8(); std::cout << std::endl; odfaeg::FastDelegate<void> f9(bar,"de"); f9(); f9.setParam("def"); f9(); std::cout << std::endl; odfaeg::FastDelegate<int> f10(goo,18); std::cout << f10(); f10.setParam(19); std::cout << f10(); std::cout << std::endl; }
C'est assez complexe car ton tuple ne doit pas stocker de const char* qui risque de créer des fuite mémoire mais des std::string, ça mon code le fait (mais uniquement pour std::string pas les autre basic_string), par contre ça veut dire qu'il faut explicitement repasser sur du const char* à l'appel, ça peut se faire mais c'est pas trivial. De toute manière tu es sensé utiliser std::string et "abc"s maintenant en C++.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 void foo(const char*);
J'ai commencé à regarder la gestion des références, mais pour le moment je me retrouve à partir sur une piste à base de std::unique_ptr<void> qui me plait assez peu. L'objectif (avec cette piste ou une autre) c'est de changer les types du tuple pour des types plus généraux qui peuvent convenir à tout ce qui peut être converti vers le type du foncteur et à std::reference_wrapper ce qui fait un paquet de monde, d'où la piste du std::unique_ptr<void>. Sachant que ca devra se raffiner en "plein de type sauf les types placeholder pour pouvoir les gérer".
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager