J'en étais resté à l'idée que void* pouvait représenter n'importe quel
pointeur, y compris de fonction. Mais voilà qu'avec des fonctions membres
ça ne marche pas :
-----
class Toto {
public:
bool foo();
} ;
bool bar();
typedef bool(Toto::*member_fun_ptr)();
typedef bool(*fun_ptr)();
int main(){
member_fun_ptr test=&Toto::foo;// typedef OK
void *ptr;
fun_ptr fp=&bar;
g++ me dit :
-----
In function ‘int main()’:
19:42: warning: converting from ‘bool (Toto::*)()’ to ‘void*’ [-Wpmf-conversions]
20:59: error: invalid cast from type ‘void*’ to type ‘member_fun_ptr {aka bool (Toto::*)()}’
-----
Y a-t-il un moyen pour que ça fonctionne, et si oui comment ? Il me semble
que je pourrais remplacer void* par une union de tous les types de
pointeurs que j'utiliserai, mais c'est un peu lourdingue.
Accessoirement, pourquoi cette erreur ? (Et je suis un peu surpris qu'on
ait un warning dans un sens et une erreur dans l'autre.)
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Lucas Levrel
Le 20 août 2015, Lucas Levrel a écrit :
J'en étais resté à l'idée que void* pouvait représenter n'importe quel pointeur, y compris de fonction. Mais voilà qu'avec des fonctions membres ça ne marche pas :
----- class Toto { public: bool foo(); } ;
bool bar();
typedef bool(Toto::*member_fun_ptr)();
typedef bool(*fun_ptr)();
int main(){ member_fun_ptr test=&Toto::foo;// typedef OK void *ptr; fun_ptr fp=&bar;
g++ me dit : ----- In function ‘int main()’: 19:42: warning: converting from ‘bool (Toto::*)()’ to ‘void*’ [-Wpmf-conversions] 20:59: error: invalid cast from type ‘void*’ to type ‘member_fun_ptr {aka bool (Toto::*)()}’ -----
Y a-t-il un moyen pour que ça fonctionne, et si oui comment ? Il me semble que je pourrais remplacer void* par une union de tous les types de pointeurs que j'utiliserai, mais c'est un peu lourdingue.
Addendum, au cas où ça aide à résoudre le problème : toutes les fonctions sur lesquelles je prends un pointeur sont membres de la même classe Toto.
-- LL Ἕν οἶδα ὅτι οὐδὲν οἶδα (Σωκράτης)
Le 20 août 2015, Lucas Levrel a écrit :
J'en étais resté à l'idée que void* pouvait représenter n'importe quel
pointeur, y compris de fonction. Mais voilà qu'avec des fonctions membres ça
ne marche pas :
-----
class Toto {
public:
bool foo();
} ;
bool bar();
typedef bool(Toto::*member_fun_ptr)();
typedef bool(*fun_ptr)();
int main(){
member_fun_ptr test=&Toto::foo;// typedef OK
void *ptr;
fun_ptr fp=&bar;
g++ me dit :
-----
In function ‘int main()’:
19:42: warning: converting from ‘bool (Toto::*)()’ to ‘void*’
[-Wpmf-conversions]
20:59: error: invalid cast from type ‘void*’ to type ‘member_fun_ptr {aka
bool (Toto::*)()}’
-----
Y a-t-il un moyen pour que ça fonctionne, et si oui comment ? Il me semble
que je pourrais remplacer void* par une union de tous les types de pointeurs
que j'utiliserai, mais c'est un peu lourdingue.
Addendum, au cas où ça aide à résoudre le problème : toutes les fonctions
sur lesquelles je prends un pointeur sont membres de la même classe Toto.
J'en étais resté à l'idée que void* pouvait représenter n'importe quel pointeur, y compris de fonction. Mais voilà qu'avec des fonctions membres ça ne marche pas :
----- class Toto { public: bool foo(); } ;
bool bar();
typedef bool(Toto::*member_fun_ptr)();
typedef bool(*fun_ptr)();
int main(){ member_fun_ptr test=&Toto::foo;// typedef OK void *ptr; fun_ptr fp=&bar;
g++ me dit : ----- In function ‘int main()’: 19:42: warning: converting from ‘bool (Toto::*)()’ to ‘void*’ [-Wpmf-conversions] 20:59: error: invalid cast from type ‘void*’ to type ‘member_fun_ptr {aka bool (Toto::*)()}’ -----
Y a-t-il un moyen pour que ça fonctionne, et si oui comment ? Il me semble que je pourrais remplacer void* par une union de tous les types de pointeurs que j'utiliserai, mais c'est un peu lourdingue.
Addendum, au cas où ça aide à résoudre le problème : toutes les fonctions sur lesquelles je prends un pointeur sont membres de la même classe Toto.
-- LL Ἕν οἶδα ὅτι οὐδὲν οἶδα (Σωκράτης)
Alain Ketterlin
Lucas Levrel writes:
[...]
class Toto { public: bool foo(); } ;
bool bar();
typedef bool(Toto::*member_fun_ptr)();
typedef bool(*fun_ptr)();
int main(){ member_fun_ptr test=&Toto::foo;// typedef OK void *ptr; fun_ptr fp=&bar;
g++ me dit : ----- In function âint main()â: 19:42: warning: converting from âbool (Toto::*)()â to âvoid*â [-Wpmf-conversions] 20:59: error: invalid cast from type âvoid*â to type â member_fun_ptr {aka bool (Toto::*)()}â -----
Y a-t-il un moyen pour que ça fonctionne, et si oui comment ? Il me semble que je pourrais remplacer void* par une union de tous les types de pointeurs que j'utiliserai, mais c'est un peu lourdingue.
g++ me dit :
-----
In function âint main()â:
19:42: warning: converting from âbool (Toto::*)()â to âvoid*â
[-Wpmf-conversions]
20:59: error: invalid cast from type âvoid*â to type â member_fun_ptr
{aka bool (Toto::*)()}â
-----
Y a-t-il un moyen pour que ça fonctionne, et si oui comment ? Il me
semble que je pourrais remplacer void* par une union de tous les
types de pointeurs que j'utiliserai, mais c'est un peu lourdingue.
g++ me dit : ----- In function âint main()â: 19:42: warning: converting from âbool (Toto::*)()â to âvoid*â [-Wpmf-conversions] 20:59: error: invalid cast from type âvoid*â to type â member_fun_ptr {aka bool (Toto::*)()}â -----
Y a-t-il un moyen pour que ça fonctionne, et si oui comment ? Il me semble que je pourrais remplacer void* par une union de tous les types de pointeurs que j'utiliserai, mais c'est un peu lourdingue.
En résumé : c'est illégal, au mieux dépendant de l'implémentation.
Merci, je vais m'y plonger.
C'est quoi "ça" (ce qui doit fonctionner) ?
La même chose qu'avec une fonction globale ou tout autre objet : pouvoir « caster » vers et depuis void*. Ça permet de stocker sous une seule « forme » des pointeurs de différents types. (Je ne vois pas ce qui pose problème pour une fonction membre si ça n'en pose pas pour une fonction globale. Je suppose que je vais l'apprendre par les liens que tu donnes.)
Que peux-tu faire avec un pointeur de fonction/membre dont tu ne connais pas le type ?
Bien sûr je stocke aussi un index qui identifie le type de l'objet pointé.
Par exemple j'aurais : enum { A, B, C }; vector<int> type_objets; vector<void*> objets; ... switch(type_objets[i]){ case A: typeA * objetA_ptr = reinterpret_cast<typeA*>(objets[i]); ... case B: ... }
(Et si vraiment tu as du code qui doit fonctionner pour plusieurs types, tu auras du mal à échapper aux template.)
Je n'ai jamais codé de templates, mais en l'occurence le code est très différent à l'intérieur des différents « case » ci-dessus donc je n'ai pas l'impression que ce concept s'applique.
En résumé : c'est illégal, au mieux dépendant de l'implémentation.
Merci, je vais m'y plonger.
C'est quoi "ça" (ce qui doit fonctionner) ?
La même chose qu'avec une fonction globale ou tout autre objet : pouvoir
« caster » vers et depuis void*. Ça permet de stocker sous une seule
« forme » des pointeurs de différents types. (Je ne vois pas ce qui pose
problème pour une fonction membre si ça n'en pose pas pour une fonction
globale. Je suppose que je vais l'apprendre par les liens que tu donnes.)
Que peux-tu faire avec un pointeur de fonction/membre dont tu ne connais
pas le type ?
Bien sûr je stocke aussi un index qui identifie le type de l'objet pointé.
Par exemple j'aurais :
enum { A, B, C };
vector<int> type_objets;
vector<void*> objets;
...
switch(type_objets[i]){
case A:
typeA * objetA_ptr = reinterpret_cast<typeA*>(objets[i]);
...
case B:
...
}
(Et si vraiment tu as du code qui doit fonctionner pour plusieurs types,
tu auras du mal à échapper aux template.)
Je n'ai jamais codé de templates, mais en l'occurence le code est très
différent à l'intérieur des différents « case » ci-dessus donc je n'ai pas
l'impression que ce concept s'applique.
En résumé : c'est illégal, au mieux dépendant de l'implémentation.
Merci, je vais m'y plonger.
C'est quoi "ça" (ce qui doit fonctionner) ?
La même chose qu'avec une fonction globale ou tout autre objet : pouvoir « caster » vers et depuis void*. Ça permet de stocker sous une seule « forme » des pointeurs de différents types. (Je ne vois pas ce qui pose problème pour une fonction membre si ça n'en pose pas pour une fonction globale. Je suppose que je vais l'apprendre par les liens que tu donnes.)
Que peux-tu faire avec un pointeur de fonction/membre dont tu ne connais pas le type ?
Bien sûr je stocke aussi un index qui identifie le type de l'objet pointé.
Par exemple j'aurais : enum { A, B, C }; vector<int> type_objets; vector<void*> objets; ... switch(type_objets[i]){ case A: typeA * objetA_ptr = reinterpret_cast<typeA*>(objets[i]); ... case B: ... }
(Et si vraiment tu as du code qui doit fonctionner pour plusieurs types, tu auras du mal à échapper aux template.)
Je n'ai jamais codé de templates, mais en l'occurence le code est très différent à l'intérieur des différents « case » ci-dessus donc je n'ai pas l'impression que ce concept s'applique.
Par exemple j'aurais : enum { A, B, C }; vector<int> type_objets; vector<void*> objets; ... switch(type_objets[i]){ case A: typeA * objetA_ptr = reinterpret_cast<typeA*>(objets[i]); ... case B: ... }
OK, mais c'est surtout l'endroit où tu appelles ta fonction qui est important (et la provenance des paramètres qu'elles prennent).
Il me semble que ce que tu recherches est std::function, qui te permet de conserver des "callables", que tu construis soit avec des lambdas, soit avec std::bind, soit avec tes propres classes. Quelques infos à :
Par exemple j'aurais :
enum { A, B, C };
vector<int> type_objets;
vector<void*> objets;
...
switch(type_objets[i]){
case A:
typeA * objetA_ptr = reinterpret_cast<typeA*>(objets[i]);
...
case B:
...
}
OK, mais c'est surtout l'endroit où tu appelles ta fonction qui est
important (et la provenance des paramètres qu'elles prennent).
Il me semble que ce que tu recherches est std::function, qui te permet
de conserver des "callables", que tu construis soit avec des lambdas,
soit avec std::bind, soit avec tes propres classes. Quelques infos à :
Par exemple j'aurais : enum { A, B, C }; vector<int> type_objets; vector<void*> objets; ... switch(type_objets[i]){ case A: typeA * objetA_ptr = reinterpret_cast<typeA*>(objets[i]); ... case B: ... }
OK, mais c'est surtout l'endroit où tu appelles ta fonction qui est important (et la provenance des paramètres qu'elles prennent).
Il me semble que ce que tu recherches est std::function, qui te permet de conserver des "callables", que tu construis soit avec des lambdas, soit avec std::bind, soit avec tes propres classes. Quelques infos à :
Même sans aller chercher le C (que je mélange car j'ai appris sur le tas, mais je compile avec g++), pourquoi les lignes suivantes ne donnent-elles pas d'erreur ? ptr=reinterpret_cast<void*>( fp ); fp=reinterpret_cast<fun_ptr>( ptr );
Par contre, si tu utilises un type "pointeur de fonction" (p.ex void (*)(void *)), tu peux caster entre types différents. Cf par exemple :
L'idée est que les données (void *) et les fonctions (pointeurs de fonction/membre) ne sont pas forcément stockées dans des zones de mémoire de même nature, ne serait-ce qu'à cause de W^X. Donc les deux types de pointeurs ne sont pas considérés comme compatibles.
OK, merci. W^X ?
Il me semble que ce que tu recherches est std::function, qui te permet de conserver des "callables", que tu construis soit avec des lambdas, soit avec std::bind, soit avec tes propres classes. Quelques infos à :
Même sans aller chercher le C (que je mélange car j'ai appris sur le tas,
mais je compile avec g++), pourquoi les lignes suivantes ne donnent-elles
pas d'erreur ?
ptr=reinterpret_cast<void*>( fp );
fp=reinterpret_cast<fun_ptr>( ptr );
Par contre, si tu
utilises un type "pointeur de fonction" (p.ex void (*)(void *)), tu peux
caster entre types différents. Cf par exemple :
L'idée est que les données (void *) et les fonctions (pointeurs de
fonction/membre) ne sont pas forcément stockées dans des zones de
mémoire de même nature, ne serait-ce qu'à cause de W^X. Donc les
deux types de pointeurs ne sont pas considérés comme compatibles.
OK, merci. W^X ?
Il me semble que ce que tu recherches est std::function, qui te permet
de conserver des "callables", que tu construis soit avec des lambdas,
soit avec std::bind, soit avec tes propres classes. Quelques infos à :
Même sans aller chercher le C (que je mélange car j'ai appris sur le tas, mais je compile avec g++), pourquoi les lignes suivantes ne donnent-elles pas d'erreur ? ptr=reinterpret_cast<void*>( fp ); fp=reinterpret_cast<fun_ptr>( ptr );
Par contre, si tu utilises un type "pointeur de fonction" (p.ex void (*)(void *)), tu peux caster entre types différents. Cf par exemple :
L'idée est que les données (void *) et les fonctions (pointeurs de fonction/membre) ne sont pas forcément stockées dans des zones de mémoire de même nature, ne serait-ce qu'à cause de W^X. Donc les deux types de pointeurs ne sont pas considérés comme compatibles.
OK, merci. W^X ?
Il me semble que ce que tu recherches est std::function, qui te permet de conserver des "callables", que tu construis soit avec des lambdas, soit avec std::bind, soit avec tes propres classes. Quelques infos à :