2017-01-22 5 views
2

Y a-t-il un moyen de faire quelque chose comme ça?Existe-t-il un moyen de créer un alias d'une valeur enum?

enum MyType { 
    Left, 
    Right, 

    #[cfg(universe = "normal")] 
    Port = Left, 
    #[cfg(universe = "normal")] 
    Starboard = Right, 

    #[cfg(universe = "mirror")] 
    Port = Right, 
    #[cfg(universe = "mirror")] 
    Starboard = Left, 

} 

Si vous essayez réellement, vous obtenez cette erreur (je dû ajouter MyType::):

error[E0080]: constant evaluation error 
--> <anon>:9:12 
    | 
9 |  Port = MyType::Left, 
    |   ^^^^^^^^^^^^ unimplemented constant expression: enum variants 

Here est où cette erreur est déclenchée.

Répondre

1

Votre implémentation n'a aucun sens. Regardez une version plus simple:

enum MyType { 
    One, 
    Two = One, 
} 

Ou dit d'une autre manière:

enum MyType { 
    One = 1, 
    Two = 1, 
} 

Vous demandez au compilateur de créer deux variantes de ENUM qui sont les mêmes. Mais tout le point d'enums est qu'ils sont exclusive l'un de l'autre.

Au lieu de cela, il suffit de créer une constante:

enum MyType { 
    One, 
} 

const TWO: MyType = MyType::One; 
+0

Oui J'essaie de créer des alias. Rust a déjà des alias de type sans problème. Pouvez-vous donner un exemple d'une manière dont le support des alias de variant enum casserait quelque chose parce que je ne peux pas voir. – Timmmm

+0

@Timmmm: Le problème est la correspondance de modèle. Quel bras est pris au cas où vous auriez 'match x {One => {}, Two => {}}'? –

+0

Ce n'est pas un problème. Il se comporterait exactement comme si vous écriviez 'match x {One => {}, One => {}}', c'est-à-dire imprime une erreur. (L'erreur qu'il imprime réellement est 'C'est un modèle inaccessible'.) – Timmmm

2

Pas pour autant que je sais.

Les énumérations dans Rust ne sont pas un "paquet de valeurs constantes" comme elles le sont en C. Il est possible d'associer une valeur numérique aux constantes, mais c'est tout. Bien sûr, vous pouvez créer des constantes de n'importe quel nom, mais elles ne vous permettraient pas de créer un modèle correspondant à une valeur enum. En un sens, un alias sur une variante enum est un peu comme un alias sur un champ de type. Je n'ai jamais vu l'occurrence d'un seul champ identifié par deux noms; Je me demande s'il y a un langage qui le supporte.


La solution que je proposerais à mordre la balle et de créer deux énumérations séparés avec une conversion entre eux:

use std::convert::From; 

enum Side { 
    Left, 
    Right, 
} 

enum PortSide { 
    Port, 
    Starboard, 
} 

#[cfg(not(universe = "mirror"))] 
impl From<Side> for PortSide { 
    fn from(s: Side) -> PortSide { 
     match s { 
      Side::Left => PortSide::Port, 
      Side::Right => PortSide::Starboard, 
     } 
    } 
} 

#[cfg(universe = "mirror")] 
impl From<Side> for PortSide { 
    fn from(s: Side) -> PortSide { 
     match s { 
      Side::Left => PortSide::Starboard, 
      Side::Right => PortSide::Port, 
     } 
    } 
} 

De plus, je vous conseille de ne pas exiger une fonction à préciser , mais autorise un comportement par défaut en l'absence de cette fonctionnalité. Dans votre cas, "normal" semble être le comportement par défaut.

+0

Je pensais à recommander une énumération secondaire. Il semble qu'il y ait des moments où vous voudriez une représentation ou l'autre, mais pas les deux simultanément. – Shepmaster

+0

C "prend en charge" les alias de champ enum et struct en utilisant le préprocesseur through. Je ne fais que plaisanter ici - les implémentations classiques d'Unix, par ex. 'struct stat' utilise cette fonctionnalité * beaucoup *, et cela fait partie de la raison pour laquelle les champs struct et union sont préfixés (l'autre partie étant qu'elle protège la bibliothèque standard de * application * #defining quelque chose qui arrive à correspondre à une structure champ). – user4815162342