Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

performances de static_cast


Sujet :

C++

  1. #1
    Membre habitué
    performances de static_cast
    Bonjour à tous,

    Dans le cadre de mon évolution sur l'apprentissage du C++, je me met a recourir de "plus en plus" (en restant bien entendu critique sur le fait d'avoir réellement besoin de son utilité ou non) au fameux static_cast. Cependant, dans certains cas, on se retrouve avec des fonctions telles que :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    template<typename U, typename T>
    U fonction_inutile(T const var) {
    	return static_cast<U>(var);
    }

    Où, par exemple, U est de type float et T de type double (ou int peu importe). Dans le cas présent, ok, je souhaite que ma fonction transforme tout ce qui y entre en type float. Bien. Mais admettons que cette fonction soit appelée un grand nombre de fois avec T= float et un moindre nombre de fois avec T = int ; dans ce cas précis, peut il être recommandé, voire nécessaire de créer une seconde fonction (surchargée), telle que :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    template<typename U>
    U fonction_inutile(U const var) {
    	return var;
    }


    Qu'en est-il au niveau performances pure ? Car niveau implémentation, cela oblige à doubler le nombre de fonctions, rendant ainsi les opérations de compilation, développement, débogage et maintenance sensiblement plus longs.
    Si l'impact performances est présent, vers quelle solution vous orienteriez-vous ?
    Dans mon cas, par exemple, je me permet de dire "je fais le code pour un seul type, et c'est l'utilisateur qui devra s'assurer que le type de var correspond bien au type U (en gros, à l'utilisateur de venir réaliser le cast lors de l'implémentation)". Mais peut être puis-je me permettre de généraliser mon code avec la première fonction sans que cela ne risque d'impacter les performances du programme ? Ou peut-être existe-t'il un moyen plus ingénieux ?

    Merci d'avance !

  2. #2
    Membre expert
    static_cast à un coût nul. static_cast<T>(x) a le même coût que T(x), car c'est le strict équivalent d'un appel de constructeur. Faire une seconde implémentation juste pour éviter un cast ne sert strictement à rien. Surtout que dans le cadre de template on peut toujours utiliser des if constexpr et autres construction locale pour ne multiplier inutilement le code.

    Personnellement, j'ai 2 approche: soit les algos sont générique est je ne cherche pas à savoir les types, à l'utilisateur d'être cohérent ou utiliser des types spéciaux s'il ne veut pas de promotion ou autre transformation indésirable. Soit je suis strict et cela peut aller jusqu'à ne pas compiler si on me donne un float à la place d'un double. Généralement je me limite au conversion sans perte.

    Mais avant toute chose, les perfs, ça se mesure.

  3. #3
    Expert éminent sénior
    Salut,

    En fait, la question des performances d'un static_cast ne se pose absolument pas, vu que le transtypage est fait, comme le nom l'indique si bien, de manière statique; c'est à dire : à la compilation.

    Ce qui pourrait éventuellement poser un problème de performances, ce serait de (très) nombreux appels successifs à la fonction qui aurait pour but de renvoyer la valeur transtypée, à cause du processus de "mise en pile" des appels de fonctions.

    Mais le fait que ta fonction soit template te sauve de ce point de vue, car la fonction est par nature inline (il faudrait d'ailleurs le préciser si ta fonction n'est pas une fonction membre, pour éviter les problèmes à l'édition de liens), et que ta fonction est "suffisamment simple" que pour être effectivement toujours inlinée.
    Bien. Mais admettons que cette fonction soit appelée un grand nombre de fois avec T= float et un moindre nombre de fois avec T = int ; dans ce cas précis, peut il être recommandé, voire nécessaire de créer une seconde fonction (surchargée), telle que :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    template<typename U>
    U fonction_inutile(U const var) {
    	return var;
    }
    Non, cela ne servirait à rien, d'autant plus que, tel quel (comprend : avec le même nom de fonction), le compilateur le refuserait, vu qu'il sait déjà que la fonction a besoin de deux paramètres template
    Si l'impact performances est présent, vers quelle solution vous orienteriez-vous ?
    Dans mon cas, par exemple, je me permet de dire "je fais le code pour un seul type, et c'est l'utilisateur qui devra s'assurer que le type de var correspond bien au type U (en gros, à l'utilisateur de venir réaliser le cast lors de l'implémentation)". Mais peut être puis-je me permettre de généraliser mon code avec la première fonction sans que cela ne risque d'impacter les performances du programme ? Ou peut-être existe-t'il un moyen plus ingénieux
    Comme je viens de l'expliquer, le static_cast, sous cette forme (et avec des types primitifs) ne pose absolument aucun problème de performances à l'exécution

    Par contre, rien ne t'empêche, pour la facilité de l'utilisateur, de préciser le type par défaut du deuxième paramètre template, sous une forme proche de
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    template<typename U, typename T = U>
    U fonction_inutile(T const var) {
    	return static_cast<U>(var);
    }
    juste pour qu'il ne soit pas obligé d'avoir recours à un code aussi abjecte que:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    auto result = fonction_inutile<int, int>(monInt);
    (meme si on se pose décemment la question de la raison pour laquelle il aurit pu décider de le faire )

    Enfin, il n'est pas exclu que le fait de désigner cette fonction comme constexpr puisse encore améliorer les choses, même si je ne vois pas trop comment le compilateur pourrait en profiter sur ce coup
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre habitué
    Mais oui !!!! Suis-je bête.... static_cast --> static, donc transformé à la compilation ! J'avais déjà lu un truc similaire sur stack overflow et je viens quand me^me poser la question ici --'

    Sujet résolu. Merci au passage pour vos remarques intéressantes autour de ce sujet. Encore une chose d'apprise.

    Bien que cela implique dans mon cas de refactoriser tous mes opérateurs , je vais tout de même re-orienter mon code dès maintenant dans ce sens.

    Merci pour ces retours !