Pointeur de fonction membre en argument template

Le
Loïc Joly
Bonjour,

J'ai écrit le code suivant, qui provoque une erreur à la compilation.
Est-ce normal ? Y a-t-il quand même un moyen de créer un mem_fun avec g ?

template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()>
struct mem_fun
{
};

struct A
{
int f();
};

struct B : A
{
int g();
};

int main()
{
typedef int (B::*FctPtr)();
FctPtr g = &B::g; // Ok
FctPtr f = &B::f; // Ok
mem_fun<B, int, &B::g> g1; // Ok
mem_fun<B, int, &B::f> f1; // error C2440: 'specialization' :
// cannot convert from 'overloaded-function' to 'int (__thiscall
// B::* )(void)'
}


Merci,

--
Loïc
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Michel Decima
Le #308515
Bonjour,

J'ai écrit le code suivant, qui provoque une erreur à la compilation.
Est-ce normal ?


Je ne sais pas. g++-4.1.1 le rejette aussi, mais xlC-8 l'accepte sans
probleme.

Y a-t-il quand même un moyen de créer un mem_fun avec g ?

Je ne sais pas non plus, mais comme j'ai un peu du mal avec les
pointeurs sur fonction membres en tant qu'argument template...

Jean-Marc Bourguet
Le #308514
Loïc Joly
Bonjour,

J'ai écrit le code suivant, qui provoque une erreur à la
compilation. Est-ce normal ? Y a-t-il quand même un moyen de créer un
mem_fun avec g ?


Avec f je suppose?

template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()>
struct mem_fun
{
};

struct A
{
int f();
};

struct B : A
{
int g();
};

int main()
{
typedef int (B::*FctPtr)();
FctPtr g = &B::g; // Ok
FctPtr f = &B::f; // Ok
mem_fun<B, int, &B::g> g1; // Ok
mem_fun<B, int, &B::f> f1; // error C2440: 'specialization' :
// cannot convert from 'overloaded-function' to 'int (__thiscall
// B::* )(void)'
}


Il y a bien une conversion de int (A::*)() en int (B::*)() [4.11/2], ce qui
autorise
FctPtr f = &B::f;

Mais les conversions considerees pour les parametres templates sont moins
nombreuses, elle n'en fait pas partie [13.3.2/5].

Pour info:

"ComeauTest.c", line 22: error: argument of type "int (A::*)()" is incompatible
with template parameter of type "int (B::*)()"
mem_fun<B, int, &B::f> f1;
^
A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Loïc Joly
Le #308493
Loïc Joly

Bonjour,

J'ai écrit le code suivant, qui provoque une erreur à la
compilation. Est-ce normal ? Y a-t-il quand même un moyen de créer un
mem_fun avec g ?



Avec f je suppose?


Oui, f, bien entendu.

Mais les conversions considerees pour les parametres templates sont moins
nombreuses, elle n'en fait pas partie [13.3.2/5].


Merci de l'info. C'est en fait dans 14.3.2/5 si d'autres veulent voir.
Il me reste encore à bien comprendre la motivation de cette règle.
Néanmoins, en attendant, en convertissant explicitement, ça marche :

mem_fun<B, int, FctPtr(&B::f)> f1;

--
Loïc


Jean-Marc Bourguet
Le #308492
Loïc Joly
Loïc Joly
Bonjour,

J'ai écrit le code suivant, qui provoque une erreur à la
compilation. Est-ce normal ? Y a-t-il quand même un moyen de créer un
mem_fun avec g ?
Avec f je suppose?



Oui, f, bien entendu.

Mais les conversions considerees pour les parametres templates sont moins
nombreuses, elle n'en fait pas partie [13.3.2/5].


Merci de l'info. C'est en fait dans 14.3.2/5 si d'autres veulent voir. Il
me reste encore à bien comprendre la motivation de cette règle.


La, c'est pas pour moi.

Néanmoins, en attendant, en convertissant explicitement, ça marche :

mem_fun<B, int, FctPtr(&B::f)> f1;


Tres amusant, les notations casts (que ce soit static_cast ou (FctPtr)) ne
fonctionnent pas. La motivation n'est a nouveau pas pour moi.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Loïc Joly
Le #308491
Loïc Joly
Il
me reste encore à bien comprendre la motivation de cette règle.



La, c'est pas pour moi.


Après lecture de l'issue 440, qui a l'air d'être le même sujet, bien que
l'exemple soit plus complexe, en faisant intervenir des valeurs par
défaut, j'ai bien peur ne ne jamais avoir d'explication technique...



Néanmoins, en attendant, en convertissant explicitement, ça marche :

mem_fun<B, int, FctPtr(&B::f)> f1;



Tres amusant, les notations casts (que ce soit static_cast ou (FctPtr)) ne
fonctionnent pas. La motivation n'est a nouveau pas pour moi.


Chez moi (MSVC8.0), les notations :
mem_fun<B, int, static_cast<FctPtr>(&B::f)> f1;
mem_fun<B, int, (FctPtr)&B::f> f1;

Compilent aussi.

--
Loïc


Jean-Marc Bourguet
Le #308490
Loïc Joly
Néanmoins, en attendant, en convertissant explicitement, ça marche :

mem_fun<B, int, FctPtr(&B::f)> f1;
Tres amusant, les notations casts (que ce soit static_cast ou (FctPtr)) ne

fonctionnent pas. La motivation n'est a nouveau pas pour moi.


Chez moi (MSVC8.0), les notations :
mem_fun<B, int, static_cast<FctPtr>(&B::f)> f1;
mem_fun<B, int, (FctPtr)&B::f> f1;


J'avais en fait simplement essaye static_cast et (FctPtr) avec Como et je
t'ai fait confiance pour l'appel fonctionnel. Je viens donc d'essayer
FctPtr(...) et j'ai le meme message qu'avant

"ComeauTest.c", line 22: error: non-integral operation not allowed in nontype
template argument
mem_fun<B, int, FctPtr(&B::f)> f1;
^
A relecture de 14.3.2/1 c'est clair que c'est interdit.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Loïc Joly
Le #308489

J'avais en fait simplement essaye static_cast et (FctPtr) avec Como et je
t'ai fait confiance pour l'appel fonctionnel. Je viens donc d'essayer
FctPtr(...) et j'ai le meme message qu'avant

"ComeauTest.c", line 22: error: non-integral operation not allowed in nontype
template argument
mem_fun<B, int, FctPtr(&B::f)> f1;
^
A relecture de 14.3.2/1 c'est clair que c'est interdit.


— the address of an object or function with external linkage, including
function templates and function templateids but excluding nonstatic
class members, expressed as & idexpression where the & is optional if
the name refers to a function or array; or

En effet, il semble qu'on puisse en théorie uniquement avoir directement
un pointeur de fonction, et non pas une expression (même constante) qui
en retourne un. Encore une autre limitation...

Donc, j'ai si j'ai bien compris le choix entre le cast, qui marche sur
mon compilo, mais n'est pas légal, et avoir dans la classe B :

struct B : A
{
int g();
int f() {return A::f();}
};

Qui n'est vraiment pas terrible...

--
Loïc

Jean-Marc Bourguet
Le #308488
Loic_Joly
En effet, il semble qu'on puisse en théorie uniquement avoir directement un
pointeur de fonction, et non pas une expression (même constante) qui en
retourne un. Encore une autre limitation...

Donc, j'ai si j'ai bien compris le choix entre le cast, qui marche sur mon
compilo, mais n'est pas légal, et avoir dans la classe B :

struct B : A
{
int g();
int f() {return A::f();}
};

Qui n'est vraiment pas terrible...


J'en ai bien l'impression.
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Publicité
Poster une réponse
Anonyme