1 votes

La fonctionnalité des constantes doit-elle être étendue ?

EDIT : cette question pourrait probablement utiliser un titre plus approprié. N'hésitez pas à en suggérer un dans les commentaires.

En utilisant le C++ avec un grand ensemble de classes, j'ai un jour rencontré une situation dans laquelle const est devenu une source de tracas, non pas à cause de sa fonctionnalité, mais parce qu'il a une définition très simpliste. Son applicabilité à un entier ou une chaîne de caractères est évidente, mais pour des classes plus compliquées, il y a souvent plusieurs propriétés qui pourraient être modifiées indépendamment les unes des autres. J'imagine que de nombreuses personnes ont dû apprendre ce que le mutable mot-clé fait pourrait avoir eu des frustrations similaires.

L'exemple le plus évident pour moi serait une classe de matrice, représentant une transformation 3D. Une matrice représentera à la fois une translation et une rotation, chacune d'entre elles pouvant être modifiée sans modifier l'autre. Imaginez la classe et les fonctions suivantes avec l'ajout hypothétique de "multi-property const".

class Matrix {
     void translate(const Vector & translation) const("rotation");
     void rotate(const Quaternion & rotation) const("translation");
}

public void spin180(const("translation") & Matrix matrix);
public void moveToOrigin(const("rotation") & Matrix matrix);

Ou imaginez des mots-clés const prédéfinis comme "_comparable" qui vous permettent de définir des fonctions qui modifient l'objet à volonté tant que vous promettez de ne rien changer qui affecterait l'ordre de tri de l'objet, facilitant ainsi l'utilisation d'objets dans des conteneurs triés.

Quels seraient les avantages et les inconvénients de ce type de fonctionnalité ? Pouvez-vous imaginer une utilisation pratique de cette fonctionnalité dans votre code ? Existe-t-il une bonne approche pour réaliser ce type de fonctionnalité avec la fonctionnalité actuelle du mot-clé const ?

Gardez à l'esprit

  • Je sais qu'une telle fonctionnalité linguistique pourrait facilement faire l'objet d'abus. On peut dire la même chose de nombreuses caractéristiques du langage C++.
  • Comme const Je m'attendrais à ce qu'il s'agisse d'une fonctionnalité strictement liée à la compilation.
  • Si vous pensez déjà const est la chose la plus stupide depuis la boue tranchée, je considère que vous pensez la même chose à ce sujet. Pas besoin de poster, merci.

EDIT : En réponse au commentaire de SBK sur le marquage des membres, je suggère que vous n'en avez pas. Pour les classes / membres marqués const, cela fonctionne exactement comme cela a toujours été le cas. Pour tout ce qui est marqué const("foo"), il traite tous les membres comme mutables, sauf indication contraire, laissant à l'auteur de la classe le soin de s'assurer que ses fonctions fonctionnent comme prévu. En outre, dans une matrice représentée en interne comme un tableau 2D, vous ne pouvez pas marquer les champs individuels comme const ou non const pour la translation ou la rotation, car tous les degrés de liberté se trouvent dans une seule déclaration de variable.

6voto

Loki Astari Points 116129

Scott Meyers travaillait sur un système d'expansion du langage avec des contraintes arbitraires (en utilisant des modèles).

Ainsi, vous pourriez dire qu'une fonction/méthode est Verified, ThreadSafe (etc. ou toute autre contrainte de votre choix). Ensuite, les fonctions ainsi contraintes ne pourraient appeler que d'autres fonctions ayant au moins (ou plus) de contraintes. (Par exemple, une méthode marquée ThreadSafe ne pourrait appeler qu'une autre méthode marquée ThreadSafe (à moins que le codeur ne rejette explicitement cette contrainte).

Voici l'article :
http://www.artima.com/cppsource/codefeatures.html

Ce qui m'a plu, c'est que les contraintes sont appliquées au moment de la compilation.

5voto

T.E.D. Points 26829

Dans les cas où vous avez des groupes de membres qui sont soit constants ensemble, soit mutables ensemble, ne serait-il pas aussi logique de formaliser cela en les mettant ensemble dans leur propre classe ? Cela peut être fait aujourd'hui sans changer le langage.

3voto

Samuel Danielson Points 1043

Raffinement

Lorsqu'un ADT est indiscernable de lui-même après une certaine opération, la propriété const est valable pour l'ensemble de l'ADT. Vous souhaitez définir la constance partielle.

Dans votre exemple d'ordre de tri, vous affirmez que l'opérateur< de l'ADT est invariant sous une autre opération sur l'ADT. Vos noms de constantes ad-hoc tels que "rotation" sont définis par l'ensemble des opérations pour lesquelles l'ADT est invariant. Nous pourrions laisser l'invariant sans nom et simplement lister les opérations qui sont invariantes dans const(). En raison de la surcharge, les fonctions doivent être spécifiées avec leur déclaration complète.

void set_color (Color c) const (operator<, std::string get_name());
void set_name  (std::string name) const (Color get_color());

Les noms const peuvent donc être considérés comme un formalisme - leur existence ou leur absence ne change pas la puissance du système. Mais 'typedef' peut être utilisé pour nommer une liste d'invariants si cela s'avère utile.

typedef const(operator<, std::string get_name()) DontWorryOnlyNameChanged;

Il serait difficile de trouver de bons noms pour de nombreux cas.

Utilité

L'intérêt de const est que le compilateur peut le vérifier. Il s'agit d'un autre type de const.

Mais je vois un gros défaut dans tout ça. À partir de votre exemple de matrice, je pourrais déduire à tort que la rotation et la translation sont indépendantes et donc commutatives. Mais il y a une dépendance évidente des données et la multiplication de la matrice n'est pas commutative. Il est intéressant de noter que c'est un exemple où la constance partielle est invariante sous l'application répétée de l'une ou l'autre mais pas des deux. Par exemple, 'translate' serait surpris de constater que son objet a été déplacé en raison d'une rotation après une précédente translation. Peut-être ai-je mal compris la signification de rotate et translate. Mais c'est là le problème, cette constance semble maintenant ouverte à l'interprétation. Nous avons donc besoin de ... roulement de tambour ... De la logique.

Logique

Il semble que votre proposition soit analogue au typage dépendant. Avec un système de types suffisamment puissant, presque tout peut être prouvé au moment de la compilation. Votre intérêt est dans les prouveurs de théorèmes et la théorie des types, pas dans le C++. Regardez la logique intuitionniste, le calcul séquentiel, la logique de Hoare et Coq.

Maintenant, j'ai fait le tour. Donner un nom a de nouveau un sens,

int times_2(int n) const("divisible_by_3");

puisque divisible_by_3 est en fait un type. Voici un type de nombre premier en Qi. Bienvenue dans le terrier du lapin. Et je faisais semblant d'arriver à quelque chose. Quel est cet endroit ? Pourquoi n'y a-t-il pas d'horloges ici ?

1voto

Jonathan Graehl Points 6460

Ces concepts de haut niveau sont utiles pour un programmeur.

Si je voulais rendre la constance plus fine, je le ferais de manière structurelle :

struct C { int x; int y; };

C const<x> *c;
C const<x,y> *d;
C const& e;
C &f;

c=&e; // fail, c->y is mutable via c
d=&e;
c=&f;
d=c;

Si vous me permettez d'exprimer une préférence pour un champ d'application qui privilégie au maximum les méthodes constantes (la surcharge normale préférerait la méthode non constante si mon ref/pointeur est non constant), alors le compilateur ou une analyse statique autonome pourrait déduire pour moi les ensembles de membres obligatoirement constants.

Bien sûr, tout cela est discutable à moins que vous ne prévoyiez d'implémenter un préprocesseur qui prenne l'agréable const C++ de haut niveau à grain fin et le traduise en casting-away-const C++. Nous n'avons même pas encore C++0x.

1voto

Michael Ekstrand Points 12849

Cela pourrait être intéressant, mais l'une des fonctions utiles de l'application const La définition simple de l'expression est que le compilateur peut la vérifier. Si vous commencez à ajouter des contraintes arbitraires, telles que "ne peut pas changer l'ordre de tri", le compilateur tel qu'il est actuellement ne peut pas le vérifier. De plus, le problème de la vérification par le compilateur de contraintes arbitraires est, dans le cas général, impossible à résoudre en raison du problème de l'arrêt. Je préférerais que la fonctionnalité reste limitée à ce qui peut effectivement être vérifié par un compilateur.

Des travaux sont en cours pour permettre aux compilateurs de vérifier de plus en plus de choses - des systèmes de types sophistiqués (y compris des systèmes de types dépendants), et des travaux tels que ceux réalisés dans SPARKAda, permettant la vérification assistée par le compilateur de diverses contraintes - mais ils finissent tous par atteindre les limites théoriques de l'informatique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X