web-dev-qa-db-fra.com

Pourquoi les alias de type en C ++ utilisent-ils "using" au lieu de "typedef" dans leur syntaxe?

De toute évidence, les alias de type et les alias de type basés sur des modèles sont sémantiquement équivalents aux typedefs et à une extension de typedefs pour prendre en charge le modèle. Comment se fait-il qu'une nouvelle syntaxe avec le mot clé using ait été créée pour ceux-ci au lieu d'utiliser des typedefs pour la première et une extension de syntaxe avec le mot typedef.

Remarque: ce n'est pas un clone de la question "différence entre l'utilisation et typedef". Je sais que using donne l'avantage de définir une famille de typedefs. Ce que je demande, c'est pourquoi les gens standard ont décidé que cette extension utilise le mot clé using au lieu du mot clé typedef. Cela semble simplement ajouter de la confusion dans la langue.

37
tohava

Ce que vous proposez a en fait été proposé en 2002 dans le document N1406 par Herb Sutter. Cela permettrait, par exemple, d'écrire:

template<typename T> typedef X<T,int> Xi; 

Cela a ensuite été révisé en N1449 par Gabriel Dos Reis et Mat Marcus. Ils adoptent la syntaxe using et notent ce qui suit:

Notez que nous évitons spécifiquement le terme "modèle typedef" et introduisons la nouvelle syntaxe impliquant la paire "using" et "=" pour éviter toute confusion: nous ne définissons aucun type ici, nous introduisons un synonyme (c'est-à-dire un alias) pour un abstraction d'un type-id (c'est-à-dire une expression de type) impliquant des paramètres de modèle.

Ils déclarent également:

Deux sondages de paille ont été effectués concernant la syntaxe. Une forte majorité a voté pour éviter la syntaxe du modèle typedef, en faveur de la syntaxe "=". Un deuxième vote a indiqué une forte préférence pour le mot-clé "using" par opposition à un mot comme "alias" ou l’absence de mot-clé comme dans la version provisoire de cette proposition. La motivation à utiliser n'importe quel mot-clé provenait en partie du désir d'utiliser une syntaxe qui pourrait être compatible avec la direction d'alias de non-modèle brièvement décrite ci-dessus.

Cette syntaxe a ensuite été adoptée dans la proposition finale N2258 par Gabriel Dos Reis et Bjarne Stroustrup.

30
Joseph Mansfield

Voici ce que Bjarne Stroustrup explique pourquoi ils ont introduit using au lieu d'étendre typedef:

Le mot-clé using est utilisé pour obtenir une notation linéaire "nom suivi de ce à quoi il fait référence". Nous avons essayé avec la solution typedef conventionnelle et alambiquée, mais nous n'avons jamais réussi à obtenir une solution complète et cohérente tant que nous ne nous sommes pas installés sur une syntaxe moins obscure.

Il prétend également qu'il aime davantage cette syntaxe pour les typedefs habituels:

En plus d'être importants dans le cadre des modèles, les alias de type peuvent également être utilisés comme une syntaxe différente (et mieux IMO) pour les alias de type ordinaires:

using PF = void (*)(double);

Il est tout à fait correct ici, cela semble très propre. En revanche, un typedef serait extrêmement compliqué avec le nom quelque part au milieu:

typedef void(*PF)(double);

Voici une explication (voir page 4) de leur proposition qui est encore plus approfondie:

Il a été suggéré de (ré) utiliser le mot-clé typedef - comme cela est fait dans l'article [4] - pour introduire des alias de modèle:

template<class T>
typedef std::vector<T,MyAllocator<T>> Vec;

Cette notation a l'avantage d'utiliser un mot-clé déjà connu pour introduire un alias de type. Cependant, il présente également plusieurs inconvénients parmi lesquels la confusion de l'utilisation d'un mot clé connu pour introduire un alias pour un nom de type dans un contexte où l'alias ne désigne pas un type, mais un modèle; Vec n'est pas pas un alias pour un type, et ne doit pas être pris pour un nom de typedef. Le nom Vec est un nom pour la famille std::vector<*,MyAllocator<*>> - où l'astérisque est un espace réservé pour un nom de type. Par conséquent, nous ne proposons pas la syntaxe "typedef".

template<class T>
using Vec = std::vector<T,MyAllocator<T>>;

peut être lu/interprété comme: à partir de maintenant, je vais utiliser Vect<T> comme synonyme de std::vector<T,MyAllocator<T>>. Avec cette lecture, la nouvelle syntaxe pour l'aliasing semble raisonnablement logique.

Il a donc essentiellement deux points ici:

  1. Un modèle using devient une famille de types, pas un type, donc typedef est "incorrect"
  2. using peut être lu presque comme une phrase anglaise
43
gexicide