Concept : Vers quoi doit tendre le C++

Introduction

Guillaume Belz a écrit un article suite à celui que j’ai fait sur l’écriture de services en C++11. Je ne vais pas faire de redite sur le sujet qu’il a traité, je n’aborderais donc ni comment définir et vérifier des concepts en C++11 (principalement car ça devient rapidement de la technique très lié au langage) ni comment ceci sera fait en C++14, Guillaume montre quelques facettes de la proposition du comité et ceux qui veulent aller plus loin n’ont qu’à lire ce document plus en détail.

Mon approche sera plutôt de voir les redondances dans la syntaxe actuelle de l’écriture de services en C++ et de montrer ensuite comment Haskell, un langage de programmation fonctionnel, fait ceci. Je tiens à préciser dès maintenant que par la nature même très différente des paradigmes des langages, je ne ferais pas de comparaisons code à code, elles n’auraient aucun sens.

Redondance de la syntaxe du C++

Je vais illustrer ce point en m’appuyant sur le service advance (il sert à faire avancer un itérateur) de l’en-tête iterator :

template <class InputIterator, class Distance>
void advance(InputIterator& i, Distance n);

Qu’est ce qui est fondamentale dans l’écriture d’un service ? Les identifiants des objets sur lesquels s’appuie le service. Le reste est totalement superflus : le compilateur est capable de les trouver tout seul, on pourrait donc lui demander si l’on en a besoin.

Voici donc ce service en enlevant tout ce qui est superflus :

advance(& i, n);

Nuançons les choses :

  • Le type de retour peut être complexe à déterminer par le compilateur dans le cas de chemins d’execution multiples. On peut donc considérer que c’est un élément nécessaire. Ce n’est pas le cas en Haskell, le paradigme fonctionnel limite l’existence de ces chemins où le typage change.
  • Les paramètres template n’ont qu’un intérêt purement sémantique à l’heure actuelle, ils indiquent bien à l’utilisateur une information, mais ils n’indiquent rien au compilateur : des commentaires ou une documentation feraient de même. Ici ils indiquent que i vérifie le concept d’InputIterator et n vérifie celui de Distance : c’est sur ce point que les Concept du C++14 devra changer les choses.

On peut donc conclure qu’en plus de demander une information qui ne sert à rien pour le compilateur, la syntaxe du C++ en fait une répétition.

Haskell et la programmation par Concept

Voyons maintenant comment fait Haskell en prenant comme exemple le service print (il sert à afficher comme son nom l’indique) :

print :: Show a => a -> IO ()
print x = --implementation

Notons déjà que la première ligne est facultative, elle apporte une information supplémentaire au compilateur, si l’on a pas d’information à donner il n’est pas nécessaire de l’indiquer (en réalité elle peut être inférée, mais ce n’est pas le sujet). Ainsi lorsque cette ligne est absente, on retrouve la même quantité d’information que dans la version épurée présentée précédemment.

Voyons maintenant ce qu’apporte cette première ligne, elle concerne principalement le typage :

  • La fin (après le =>) fait correspondre des types à des modèles, comme le fait le C++ avec les template. Ici un paramètre avec un modèle a et le type de retour est IO() (je ne vais pas expliquer ce que c’est ici, aucun intérêt).
  • Le début impose des contraintes sur ces modèles : il donne au compilateur l’information que le C++ ne fait que donner sémantiquement. Ici le modèle a doit respecter le concept Show.

Haskell fournit ainsi ce que le C++14 devra proposer : de quoi définir un concept. Dans le cas du concept Show par exemple, cela donne :

class Show a where
    showsPrec :: Int -> a -> ShowS
    show      :: a   -> String
    showList  :: [a] -> ShowS

On retrouve l’idée d’un modèle et une liste de services qui doivent être proposés pour ce modèle pour qu’il respecte le concept : showsPrec, show et showList dans cet exemple. (Il y aurait plus à dire sur l’écriture de classe de types en Haskell, mais ce n’est pas le sujet).

On peut donc en conclure qu’en plus d’ajouter de l’information, Haskell supprime aussi de la redondance et offre de l’orthogonalité dans la définition des services.

Conclusion

Je n’ai pour le moment que regardé d’assez loin les dernières propositions sur les Concept du C++, il me semble cependant qu’ils vont dans la bonne direction. Il y a aussi eu des propositions qui permettraient d’avoir la même orthogonalité au niveau de la définition des services en étendant le rôle d’auto notamment.

Pour terminer cet article, j’espère qu’il aura fait prendre conscience à ceux qui l’ignoraient que ce que propose le C++ pour les concepts n’est pas révolutionnaire.

Une réflexion au sujet de « Concept : Vers quoi doit tendre le C++ »

  1. Ping : C++ et Haskell – les concepts | C++, Qt, OpenGL, CUDA

Laisser un commentaire