Y a t-il un moyen de faire ceci sans passer par decltype ?
Est-ce que le type du foncteur renvoyé par std::bind est définit dans la norme ?
Si oui, j'ai juste à regarder à quoi ces typedefs correspondent et essayer de passer outre.
Version imprimable
Y a t-il un moyen de faire ceci sans passer par decltype ?
Est-ce que le type du foncteur renvoyé par std::bind est définit dans la norme ?
Si oui, j'ai juste à regarder à quoi ces typedefs correspondent et essayer de passer outre.
Bon, j'ai tenter de ruser mais sans grand succès. Après avoir lu plus précisément le header functional, je me suis rendu compte que les 2 premiers typedefs ne servaient à rien dans mon cas.
Donc pour simplifier, j'ai ceci :
j'ai malheureusement toujours un _ , j'ai donc voulus utiliser std::result_of.Code:typedef std::_Bind<Fc(Args...)> ResultFunctorType;
Malheureusement, j'obtiens l'erreur suivante :Code:typedef typename std::result_of<(decltype(std::bind<Fc,Args...>))(Fc, Args...)>::type R;
error: a comma operator cannot appear in a constant-expression|
Est-ce un bug ou est-ce normal ?
Quelqu'un a une idée ?
Le type de retour de bind n'est pas définie.
@Joe Dralliam: Je crois que le bind du dernier draft n'est pas le même que celui de boost, et ce code :
Ne compile pas, mais compile si tu ne mets q'un seul argument à foo, compile avec bind1st et l'erreur est la même que le code que j'ai mis plus haut qui n'utilise pas de decltype et autre (un auto mais on peut l'écrire sans).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 #include<cstdlib> #include<cstddef> #include<functional> #include<tuple> #include<iostream> template<class Fc, class ...Arg> auto bind_tuple_first(Fc f, const std::tuple<Arg...>& t) -> decltype(std::bind(f, std::get<0>(t) )) { return std::bind(f, std::get<0>(t) ); } void foo(int,int){std::cout << 0;} int main () { std::function<void (int,int)> f(foo); std::tuple<int> t(0); auto f2 = bind_tuple_first(f,t); f2(0); system("PAUSE"); return EXIT_SUCCESS; }
Et il me semble bien que si la fonction prend deux arguments, qu'on fait un bind(f,0), alors le retour est un wrapper sur quelque chose qu'on peut utiliser comme ca f2(0), et qui doit appeller f(0,0).
Comment est-ce possible ? De plus, mon typedef ResultFonctorType est bel et bien le type de retour de std::bind.Citation:
Le type de retour de bind n'est pas définie.
Bha, c'est possible car c'est écrit dans le draft :
C'est donc à celui qui code la STL de faire comme il veut, dans ton cas ils ont appelé le type qui représente le wrapper _Bind<Fc(Arg...)>.Citation:
template<class F, class... BoundArgs>
unspecified bind(F&& f, BoundArgs&&... bound_args);
Sans en être certain, je dirais que ce genre de chose va de pair avec l'introduction de auto decltype et des lambda qui permettent de moins s'attacher au type et plus aux opérations effectué.
Ok merci de cette réponse. Je croyais que tu voulais dire que bind n'avais pas de type réel. En fait tu veux dire qu'il dépend de l'implémentation. Cependant, cela n'explique pas pourquoi std::result_of ne marche pas.Citation:
C'est donc à celui qui code la STL de faire comme il veut, dans ton cas ils ont appelé le type qui représente le wrapper _Bind<Fc(Arg...)>.
En effet.Citation:
Sans en être certain, je dirais que ce genre de chose va de pair avec l'introduction de auto decltype et des lambda qui permettent de moins s'attacher au type et plus aux opérations effectué.
decltype ne passe pas sur bind<>, car il n'arrive pas à déterminer le type de la fonction car il existe plusieurs versions.
Mais si à la place d'utiliser result_of tu passes directement par decltype sur un appel à bind ca marche :
Mais ca revient en gros à utiliser auto et -> decltype, comme on l'a fait au début du thread, c'est juste plus verbeux (et je suis presque certain que le code ne marchera pas mieux ...)Code:
1
2 typedef decltype(std::bind(F(),Arg()...)) R;
Oui, mais la chose du début ne compile pas avec gcc4.5, je vais voir si celle la compile.
ne marche pas : le compilateur me dit qu'il ne peut appelé Fc sans paramètres.Code:typedef decltype(std::bind(Fc(),Args()...)) R;
J'ai tout de même une question, à quoi servent les parenthèses après Args ?
Pourquoi le compilateur n'accepte-il pas quand je met Fc sans les parenthèses ?
(error=function returning a function).
Compile sans problème chez moi.Code:
1
2
3
4
5
6 template<class Fc, class ...Arg> struct bind_trait { typedef decltype(std::bind(Fc(),Arg()...)) Type; };
Si je me trompe pas Arg()... c'est comme Fc() (une instanciation), mais pour une liste d'argument, donc avec int,int, ca va faire 0,0 (si il y a zero-initialisation, chose dont je ne suis pas certain).
Il faut donc un constructeur par défaut ? Ou je n'ai rien compris...
Avec cette technique oui, mais je crois que pour un premier jet tu peus te restreindre à des chose DefaultConstrcutible, tu verras après pour adapter.
Je serrais partie sur un truc comme ca :
Ca compile, mais ca ne marche pas lors de l'utilisation, je dois oublier un détail sur les templates qui fait que ca marche pas. (et de toute manière ca ne marchera pas dans toute les situations à cause de bind AMHA)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 template<size_t N> struct Help { template<class F, class ...Arg> auto Do(F&& f, const std::tuple<Arg...>& t) -> decltype(Help<N-1>::Do(std::bind(f, std::get<(sizeof...(Arg))-N>(t)),t)) { return Help<N-1>::Do(std::bind(f, std::get<(sizeof...(Arg))-N>(t)),t); } }; template<> struct Help<0> { template<class F, class ...Arg> auto Do(F&& f, const std::tuple<Arg...>&) -> decltype(std::bind(f)) { return std::bind(f); } }; template<class F, class ...Arg> auto make(F&& f, const std::tuple<Arg...>& t) -> decltype(Help<sizeof...(Arg)>::Do(f, t)) { return Help<sizeof...(Arg)>::Do(f, t); }
Mes objets ne sont pas default constructible, et j'ai déjà une méthode qui marche (ce qui me permet d'avancer tout de même). J'attendrais donc une version de gcc ou decltype et auto marcheront biens ou bien que quelqu'un trouve une autre solution...
Avec gcc4.5, sa marche parfaitement. Mais j'utilise toujours quelque chose de réserver à l'implémentation.Code:typedef std::_Bind<Fc(Args...)> ResultFunctorType;
Puisqu'on est sur la fonction bind, je voudrais savoir ce que renvoie la ligne de code:
j'arrive pas à trouver.Code:bind(less<int>(),9);
Merci
On l'a écrit plus haut : le type de retour de bind n'est pas spécifie, donc il faut utiliser auto. (où alors un typedef définit par ton compilateur qui représente le type de retour comme le fait NoIdea, mais ce 'nest pas portable).
NB: Et les codes que j'ai posté avant (les premiers), ne compilait pas car j'avais oublié d'utiliser les placeholders, avec eux ca compile (je croyais qu'ils n'était pas obligatoire mais apparament si).
Je suis d'accord avec l'utilisation d'auto, c'est ce que j'ai fait.
Disons que je n'arrive pas à comprendre pourquoi cela compile:
Comme on le voit, on utilise bind avec plus<int>(), 3 ce qui est normal, mais aussia avec (bind(less<int>(),5),_1). Je m'étonne que cela compile car bind(less<int>(),5) ne signifie rien.Code:transform(V1.begin(),V1.end(),V1.begin(),bind(plus<int>(),3,(bind(less<int>(),5),_1)));
Ca applique l'algo transform à ta séquence avec le "functeur" (ca à un autre nom dans la norme, mais je trouve celui très clair), qui s'applique sur un paramètre n et qui retourne 3 + n.
Il y a utilisation de l'opérateur , (qui permet d'appeller l'expression à gauxche avant celle de droite puis de retourner celle de droite). Mais ici j'ai l'impression qu'il ne sert à rien, c'est équivalent à :
transform(V1.begin(),V1.end(),V1.begin(),bind(plus<int>(),3,_1));
J'ai une idée pour ton problème.
Comme l'a dit Joe Dralliam, le problème vient de l'utilisation de decltype avec les template variadique.
Mais ceci :
Fonctionne bien pour les type DefaultConstructible (si on met ce qu'il y a après le retourne après le decltype ca ne marche plus, il ne supporte pas quelque chose à propos des variadics).Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 template<size_t N> struct Make { template<class F, class ...Arg, class ...Extracted> static auto Do(F f, const std::tuple<Arg...>& t, Extracted... arg) -> decltype(std::bind(f,Arg()...)) { return Make<N-1>::Do(f, t, std::get<N-1>(t), arg...); } }; template<> struct Make<0> { template<class F, class ...Arg, class ...Extracted> static auto Do(F f,const std::tuple<Arg...>& , Extracted... arg) -> decltype(std::bind(f,Arg()...)) { return std::bind(f,arg...); } };
Et si tu veus utiliser un fonction qui prend en paramètre des chose non constructible, en créant un nouveau foncteur à partir du premier qui transforme les paramètre non constructible en pointeur, ca devrait marcher :
Quelque chose comme ca (à améliorer et à vérifier si ca n'existe pas déja).Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 template<class ...Arg> struct New { template<class F> struct Functor { F f; Functor(F p) : f(p) {} void operator()(Arg* ...arg) { f(*arg...); } }; template<class F> static Functor<F> Do(F f) { return Functor<F>(f); } };
Et ensuite il faut tranformer le tuples de la même manière : faire un tuple d'addresse sur les objet du premier tuple.
Et je n'ai pas essayer, mais on peut surment faire bien mieux en ne tranformant que ceux qui ne sont pas constructible et en remplacant les non-constructible par des default constructible qui peuvent aussi être construit à partir des premiers. Je pense que ca permettrait d'utiliser directement le tuple.
Un exemple "complet" (fait à la va-vite, fuite mémoire)
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 struct A { A(int){} }; void foo(A,int,int){ std::cout << 0; } template<size_t N> struct Make { template<class F, class ...Arg, class ...Extracted> static auto Do(F f, const std::tuple<Arg...>& t, Extracted... arg) -> decltype(std::bind(f,Arg()...)) { return Make<N-1>::Do(f, t, std::get<N-1>(t), arg...); } }; template<> struct Make<0> { template<class F, class ...Arg, class ...Extracted> static auto Do(F f,const std::tuple<Arg...>& , Extracted... arg) -> decltype(std::bind(f,Arg()...)) { return std::bind(f,arg...); } }; template<class ...Arg> struct New { template<class F> struct Functor { F f; Functor(F p) : f(p) {} void operator()(Arg* ...arg) { f(*arg...); } }; template<class F> static Functor<F> Do(F f) { return Functor<F>(f); } }; int main () { std::tuple<A*,int*,decltype(std::placeholders::_1)> t(new A(0),new int(),std::placeholders::_1); auto f1 = New<A,int,int>::Do(foo); auto f2 = Make<3>::Do(f1, t); f2(new int()); system("PAUSE"); return EXIT_SUCCESS; }