Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Pointeur de fonction membre en argument template

8 réponses
Avatar
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

8 réponses

Avatar
Michel Decima
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...

Avatar
Jean-Marc Bourguet
Loïc Joly writes:

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

Avatar
Loïc Joly
Loïc Joly writes:


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


Avatar
Jean-Marc Bourguet
Loïc Joly writes:

Loïc Joly writes:

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



Avatar
Loïc Joly
Loïc Joly writes:
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


Avatar
Jean-Marc Bourguet
Loïc Joly writes:

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



Avatar
Loïc Joly

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

Avatar
Jean-Marc Bourguet
Loic_Joly writes:

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