IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

[Programmation générique] Classe trait pour le type de passage d'argument

Cette fonction permet de choisir automatiquement le meilleur moyen pour le passage d'argument. Elle est tirée de l'article d'Alp Mestan sur les classes de traits et de politiques.
Avatar de 3DArchi
Rédacteur https://www.developpez.com
Le 06/11/2010 à 19:55
Bonjour, Je vous propore un nouvel élément à utiliser : [Programmation générique] Classe trait pour le type de passage d'argument

Cette fonction permet de choisir automatiquement le meilleur moyen pour le passage d'argument. Elle est tirée de l'article d'Alp Mestan sur les classes de traits et de politiques.

Qu'en pensez-vous ?
Avatar de NoIdea
Membre actif https://www.developpez.com
Le 24/01/2011 à 20:08
Juste une question, y a t-il un avantage (d'un point de vue performance) lorsqu'il s'agit d'un int de le passer par copie plutôt que par référence constante ? N'est-ce pas la même taille ?
Avatar de Emmanuel Deloget
Expert confirmé https://www.developpez.com
Le 24/01/2011 à 20:35
Citation Envoyé par NoIdea Voir le message
Juste une question, y a t-il un avantage (d'un point de vue performance) lorsqu'il s'agit d'un int de le passer par copie plutôt que par référence constante ? N'est-ce pas la même taille ?
Les références et les pointeurs ont une taille hardware égale à la taille du mot natif. La taille d'un int est décorélée de la taille de mot native. Donc non, ce n'est pas toujours la même taille (en particulier en 64 bits, ou la taille d'une référence est 64 bits tandis que l'int est resté à 32 bits sur la plupart des plateformes).

Ceci dit, passer un int en référence constante (ou toute autre donnée dont la taille est égale ou inférieure à celle du mot natif) n'a pas vraiment de sens. En termes de performance, le gain (s'il y a, et j'en doute) est négligeable.
Avatar de NoIdea
Membre actif https://www.developpez.com
Le 24/01/2011 à 20:49
Si je comprend bien, tu dis que cette classe de politique est uniquement didactique et n'est pas utilisée dans un cas réel ?
Avatar de Flob90
En attente de confirmation mail https://www.developpez.com
Le 24/01/2011 à 21:00
Non, il a juste dit que la taille d'un int n'est pas lié à la taille "natif" du système contrairement à celle d'un pointeur (d'un référence). Et que, pour les int mais aussi pour d'autre type, si la taille est inférieure à celle d'un pointeur le passage par référence ne serait pas nécessairement un gain. Et c'est exactement ce choix que permet de faire cet outil.

Ne serait-il pas mieux de comparer sizeof(T) avec sizeof(void*) plutôt que 8 ?
Avatar de Goten
Membre chevronné https://www.developpez.com
Le 24/01/2011 à 21:00
Citation Envoyé par NoIdea Voir le message
Si je comprend bien, tu dis que cette classe de politique est uniquement didactique et n'est pas utilisée dans un cas réel ?

Bien sur que si, regarde boost::call_traits
Avatar de NoIdea
Membre actif https://www.developpez.com
Le 24/01/2011 à 21:42
Non, il a juste dit que la taille d'un int n'est pas lié à la taille "natif" du système contrairement à celle d'un pointeur (d'un référence).
Il me semblait pourtant que les processeurs 64 bits préféraient les int de taille 64. En tout cas, pour les char, c'est évident.

Et que, pour les int mais aussi pour d'autre type, si la taille est inférieure à celle d'un pointeur le passage par référence ne serait pas nécessairement un gain.
Cela je l'avais compris car toute référence est pointeur caché. Cependant, bien que ce ne soit pas "nécessairement un gain", il se peut que cela ne change rien du tout. De plus, même si le pointeur à pour taille 8 octets et le int 4 octets, le gain en performance est négligeable d'après ce que j'ai compris de ceci :

En termes de performance, le gain (s'il y a, et j'en doute) est négligeable.
A moins que tu veuilles dire que c'est la référence constante qui n'apporte aucun gain.

Ne serait-il pas mieux de comparer sizeof(T) avec sizeof(void*) plutôt que 8 ?
Cela me paraitrait plus cohérent.

Donc, je redemande, dans le cas de la copie, on peut gagner jusqu'à 7 octets sur les processeurs habituels. Est-ce que cela change quelque chose au performances ?
Le compilateur n'est-il pas déjà capable d'effectuer ce genre d'optimisation ?
N'est-ce pas alourdir le temps de compilation pour pas grand chose ?
Est-ce que la copie permet au compilateur de mieux optimiser (ce qui me semble être la raison qui justifie le plus ce type de politique) ?

Bien sur, je ne dis pas que cette classe désavantage un programme, je dis juste qu'il me semble qu'elle n'apporte pas de gain majeur. Ais-je tord ?

Bien sur que si, regarde boost::call_traits
Je vais regarder voir s'il donne la raison pour laquelle il faut l'utiliser.

Concernant, toutes ces histoires de copies et de passage par référence, peut-il y avoir un gain en déclarant la variable globale (pas de copie je crois) ? Bien sur, ce serait une optimisation du compilateur pas de moi (et je n'ai aucune idée de comment marche les variables globales).
Avatar de CedricMocquillon
Membre averti https://www.developpez.com
Le 25/01/2011 à 10:03
ne faudrait-il pas en plus vérifier que le type est copie-constructible et sinon le passer par référence constante?
Avatar de Emmanuel Deloget
Expert confirmé https://www.developpez.com
Le 25/01/2011 à 14:47
Citation Envoyé par NoIdea Voir le message
Si je comprend bien, tu dis que cette classe de politique est uniquement didactique et n'est pas utilisée dans un cas réel ?
Non, elle a une réelle utilité.

Par exemple, on aurait pu réécrire std::vector<X>::push_back() ainsi :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
template <class T>
class vector
{
public:
  // il faudrait ajouter ConstParamType sur le modèle de ParamType
  void push_back(typename Calltraits<T>::ConstParamType value)
  {
    ...
  }
};
(pour info, je rappelle que le prototype donnée par C++98 est push_back(T); même pas push_back(T& const)).

T n'est pas toujours un type de base ; ça peut être absolument n'importe quoi.

Citation Envoyé par NoIdea Voir le message
Il me semblait pourtant que les processeurs 64 bits préféraient les int de taille 64. En tout cas, pour les char, c'est évident.
Plus exactement, ils font ce qu'ils veulent. Mais il y a tellement de code écrit qui définissent "typedef unsigned int uint32" que les vendeurs de compilateurs ont bien souvent décidé de laisser les int sur 32 bits. les long font généralement 64 bits (sur une architecture 64 bits, s'entend).

Citation Envoyé par NoIdea Voir le message

Cela je l'avais compris car toute référence est pointeur caché. Cependant, bien que ce ne soit pas "nécessairement un gain", il se peut que cela ne change rien du tout. De plus, même si le pointeur à pour taille 8 octets et le int 4 octets, le gain en performance est négligeable d'après ce que j'ai compris de ceci :
Il peut y avoir un gain infinitésimal, parce que le microprocesseur est optimisé pour lire des mots de 64 bits (en 64 bits, toujours). Du coup, lire un entier de 32 bits lui demande plus d'opérations microcodées. Ceci-dit, on parle de ce qui se passe dans le microcode, donc d'une fraction de l'horloge externe du microprocesseur. Il y a peu de chance pour que ça ait une répercussion à l'extérieur de celui-ci.

Citation Envoyé par NoIdea Voir le message

A moins que tu veuilles dire que c'est la référence constante qui n'apporte aucun gain.
C'est ce que j'ai dit

Citation Envoyé par NoIdea Voir le message

Donc, je redemande, dans le cas de la copie, on peut gagner jusqu'à 7 octets sur les processeurs habituels. Est-ce que cela change quelque chose au performances ?
Même réponse.

Citation Envoyé par NoIdea Voir le message

Le compilateur n'est-il pas déjà capable d'effectuer ce genre d'optimisation ?
N'est-ce pas alourdir le temps de compilation pour pas grand chose ?
Non, hélas. Le compilateur a l'obligation de faire ce qu'on lui dit de faire. Il a peu de latitude pour modifier le code (il ne peut le faire que si le code modifié se comporte exactement comme l'original).

Citation Envoyé par NoIdea Voir le message

Est-ce que la copie permet au compilateur de mieux optimiser (ce qui me semble être la raison qui justifie le plus ce type de politique) ?
C'est un débat intéressant : le compilateur peut faire des élisions de code en cas de copie d'objets lourds, notamment s'ils ne sont pas modifiés. Sur le code suivant, un compilateur intelligent n'appellera le constructeur de la classe que s'il lui fait initialiser le paramètre à partir d'une valeur qui n'est pas du type du paramètre :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template <class T>
T identify(T t)
{ return t; }

struct X
{
... (beaucoup de données)
  void do() { ... }
};

int main()
{
  X x;
  identity(x).do(); // aucune copie, grâce aux 
                      // différentes optimisations du compilateur.
}
Le problème est que ce comportement n'est pas défini par le standard (ne pas comprendre que le standard le rend indéfini ; juste qu'il n'en parle pas, et du coup, bien que n'étant pas contraire au standard, il n'est pas obligatoire pour un vendeur de compilateur de l'implémenter).

Citation Envoyé par NoIdea Voir le message

Bien sur, je ne dis pas que cette classe désavantage un programme, je dis juste qu'il me semble qu'elle n'apporte pas de gain majeur. Ais-je tord ?
Oui, parce qu'on parle de tous les types imaginables, pas seulement les types de base.

Citation Envoyé par NoIdea Voir le message

Je vais regarder voir s'il donne la raison pour laquelle il faut l'utiliser.
Ne t'inquiète pas, de telles raisons existent

Citation Envoyé par NoIdea Voir le message

Concernant, toutes ces histoires de copies et de passage par référence, peut-il y avoir un gain en déclarant la variable globale (pas de copie je crois) ? Bien sur, ce serait une optimisation du compilateur pas de moi (et je n'ai aucune idée de comment marche les variables globales).
Si tu souhaites passer par des variables globales, tu te trouves dans un autre problème : n'importe qui peut les modifier et tu sacrifie la réentrance (pas possible d'écrire une fonction récursive, pas possible d'écrire une fonction appelable depuis plusieurs threads,...).
Developpez.com décline toute responsabilité quant à l'utilisation des différents éléments téléchargés.