Partage
  • Partager sur Facebook
  • Partager sur Twitter

using , fonction int vers int

C++

Sujet résolu
    10 mai 2019 à 15:56:38

    Bonjour

    à un moment , je fais 

    using monType = int(*)(int) ;

    pour créer un type qui est : "pointeur sur une fonction prenant en paramètre un int et renvoyant un int"

    L'utilisation que j'en fais fonctionne.

    J'aimerais faire ensuite la même chose , mais sans le pointeur : un type qui est une fonction prenant un int et renvoyant un int

    Pour cela, je propose 

    using monType = int(int);
    

    Or l'utilisation que j'en fais ne compile pas

    Dois-je corriger quelque chose dans mon alias de type  ?

    Merci par avance


    -
    Edité par pseudo-simple 10 mai 2019 à 15:58:30

    • Partager sur Facebook
    • Partager sur Twitter
      10 mai 2019 à 16:05:44

      Salut,

      https://en.cppreference.com/w/cpp/utility/functional/function ?

      Je vois pas trop l'intérêt de se casser le cul avec des pointeurs sur fonctions alors qu'on a un type tout prêt pour ça ;)

      -
      Edité par Emrak 10 mai 2019 à 16:13:11

      • Partager sur Facebook
      • Partager sur Twitter
        10 mai 2019 à 16:18:45

        Salut, je te remercie pour cette apport intéressant. Je vais regarder cela après en effet.

        J'aimerais résoudre mon défi de départ.

        Par exemple si j'ai une fonction f surchargée :

        int f(int) {}
        int f(int a, double b){}

        je voudrais pouvoir faire 

        monType a = f;

        cela marche si je passe par des pointeurs de fonction, mais si je fais int(int)

        j'aimerais résoudre le problème de départ.

        Par avance merci


        -
        Edité par pseudo-simple 10 mai 2019 à 16:18:57

        • Partager sur Facebook
        • Partager sur Twitter
          10 mai 2019 à 16:20:39

          ça s'appelle du type erasure et c'est faisable avec std::function et std::bind ou les lambdas.

          #include <iostream>
          #include <functional>
          
          int a(int) { return 1; }
          int b(int, double) { return 2; }
          int c(int, bool, int) { return 3; }
          
          using func = std::function<int (int)>;
          
          int main() {
          	func fa = a;
          	func fb = std::bind(b, std::placeholders::_1, 10.0);
          	func fc = std::bind(c, std::placeholders::_1, false, 666);
          	func fx = [] (int) -> int { return 0; };
          
          	return 0;
          }

          Par contre, si ta fonction est surchargée (possède le même nom) c'est plus chiant, il faut faire un cast explicit. Certains proposent une solution élégante ressemblante à qOverload de Qt.

          -
          Edité par markand 10 mai 2019 à 16:23:48

          • Partager sur Facebook
          • Partager sur Twitter

          git is great because Linus did it, mercurial is better because he didn't.

            10 mai 2019 à 17:52:01

            Salut,

            Pourquoi crois tu que l'on parle systématiquement de pointeur de fonction ???

            C'est parce que, à l'inverse de n'importe quel types de donnée, (mais au même titre que n'importe quelle variable), une fonction a forcément une adresse mémoire.

            Et c'est logique, au point que tu aurais pu trouver la réponse par toi-même en y réfléchissant un tout petit peu, vu que, même si une fonction ne fait strictement rien, il faut pouvoir l'exécuter si tu y fait appel.

            Cela se remarque d'ailleurs très bien lorsque tu demandes au compilateur de s'arrêter à la génération du code assembleur, car un code proche de

            void foo(){
                
            }
            int main()
            {
                foo();
                
            }
            

            va se traduire en assembleur par quelque chose qui serait proche de

            	.file	"main.cpp"
            	.text
            	.globl	_Z3foov
            	.type	_Z3foov, @function
            _Z3foov:
            .LFB0:
            	.cfi_startproc
            	pushq	%rbp
            	.cfi_def_cfa_offset 16
            	.cfi_offset 6, -16
            	movq	%rsp, %rbp
            	.cfi_def_cfa_register 6
            	nop
            	popq	%rbp
            	.cfi_def_cfa 7, 8
            	ret
            	.cfi_endproc
            .LFE0:
            	.size	_Z3foov, .-_Z3foov
            	.globl	main
            	.type	main, @function
            main:
            .LFB1:
            	.cfi_startproc
            	pushq	%rbp
            	.cfi_def_cfa_offset 16
            	.cfi_offset 6, -16
            	movq	%rsp, %rbp
            	.cfi_def_cfa_register 6
            	call	_Z3foov
            	movl	$0, %eax
            	popq	%rbp
            	.cfi_def_cfa 7, 8
            	ret
            	.cfi_endproc
            .LFE1:
            	.size	main, .-main
            	.ident	"GCC: (Debian 8.3.0-6) 8.3.0"
            	.section	.note.GNU-stack,"",@progbits
            

            Observes les lignes 3 à 5, 20 à 22 et surtout 30 du résultat que l'on obtient:

            • La ligne 3 indique (faisons simple, même si ce n'est pas tout à fait juste, à l'éditeur de liens )que "_Z3foov" est un identifiant qui devra être connu depuis "n'importe où" (globl ==>"global")
            • la ligne 4 indique (à l'éditeur de liens, toujours) que "_Z3foov" n'est pas une donnée, mais que c'est une fonciton
            • la ligne 5  va poser un "jalon" qui permettra à l'éditeur de liens de savoir ... à quelle adresse mémoire commence la fonction identifiée par _Z3foov.

            Les lignes 20 à 22 font exactement pareil pour l'identifiant "main"

            Enfin, la ligne 30 indique explicitement qu'il faut faire appel à la fonction qui commence ... au jalon identifié par "_Z3foov".

            Au final, la réponse que tu cherches est que tu ne peux pas créer un alias sur ce qui sera considéré comme "une fonction à appeler" autrement que sous la forme d'un pointeur de fonction.

            Quand la notion de pointeur (de référence voire même de constance) s'avère optionnelle, comme dans les cas suivants

            using int_ptr = int *; //int_ptr est considéré comme étant un POINTEUR SUR int
            using int_ref = int &;  //int_ref  est considéré comme étant une REFERENCE SUR int
            using int_const = int const; // int_const est considéré comme étant un int CONSTANT

            tu peux l'ajouter, si tu en as besoin (et même au besoin les combiner ) sous la forme de

            using int_const_ref = int const &; //int_const_ref  est considéré comme étant une REFERENCE CONSTANTE SUR int

            Mais si la notion de pointeur est -- par nature -- obligatoire, tu ne peux pas envisager de la supprimer!


            • Partager sur Facebook
            • Partager sur Twitter
            Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
              13 mai 2019 à 13:03:02

              Un très grand merci à tous les gens qui sont venus aider sur ce fil.
              • Partager sur Facebook
              • Partager sur Twitter

              using , fonction int vers int

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown