2015-12-21 1 views
1

Si je définis des structures au niveau du module, je peux référencer des structures non encore définies.Ordre de déclaration Struct

struct S { 
    ComesLater c; 
} 
struct ComesLater {} 

Mais si je fais la même chose dans un unittest ou un bloc fonctionnel, il ne fonctionne pas:

unittest { 
    struct S { 
    ComesLater c; 
    } 
    struct ComesLater {} 
} 

Error: undefined identifier 'ComesLater'

Pourquoi? Comment puis-je obtenir des déclarations indépendantes de la commande dans les fonctions? Y a-t-il une sorte de forward-declaration en d? J'ai besoin de cela parce que je génère des structures en utilisant mixin et en ordonnant les déclarations dans l'ordre de leurs dépendances internes serait un effort, parfois impossible, s'il y a des structures de référencement circulaires. (utilisant des pointeurs.)

Répondre

2

Les déclarations à l'intérieur de fonctions, de tests unitaires ou de tout autre endroit où des instructions peuvent réellement être exécutées dépendent en effet de leur ordre, car leurs valeurs peuvent dépendre du code avant leur exécution. Pensez à une variable locale:

int a; 
writeln(a); 
a = b; 
int b = get_user_line(); 

Si l'ordre n'était pas important, quand les deux fonctions seraient-elles appelées? Est-ce qu'on demanderait à l'utilisateur une ligne avant l'écriture alors que les déclarations sont réécrites?

Le comportement actuel de rendre b une erreur de variable indéfinie le rend simple et direct.

Cela fonctionne indépendamment de l'ordre dans d'autres contextes car il n'y a pas de code exécutable sur lequel il puisse dépendre, donc il n'y a pas de comportement qui peut changer si le compilateur doit y penser différemment.

Alors:

Comment puis-je obtenir des déclarations d'ordre indépendant à l'intérieur des fonctions?

Modifiez le contexte de manière à ce qu'il n'y ait pas de code exécutable ... mettez le tout dans une autre structure! Puisque l'exécution se passe autour du support et ne se produit pas à l'intérieur, l'ordre de déclaration à l'intérieur n'a plus d'importance. Puisque vous pouvez définir presque n'importe quoi dans une structure, vous pouvez l'utiliser pour les variables, les fonctions, les autres structures, etc. Fondamentalement, tout ce que vous avez à faire est d'enrouler votre code existant à l'intérieur des parenthèses struct Holder {}. En rendant tout ce qui est statique à l'intérieur, vous pouvez simplement l'utiliser comme un conteneur et le référencer avec Holder.S, etc., à l'extérieur.

+0

Nice! Je crains de ne pas pouvoir utiliser cette solution de contournement car je pourrais générer plusieurs blocs de telles structures dans la même portée, et cela ne fonctionnera qu'une seule fois. (Alors Holder sera déjà défini.) N'y a-t-il aucune chance que vous puissiez obtenir une sorte de déclaration à terme? Ou définir un bloc de code qui n'a pas d'ordre d'exécution à l'intérieur, mais ne change pas la portée actuelle? (Similaire à Holder.) – Tamas

+2

J'ai été capable de mettre les structures dans un modèle de mixin Foo() {static struct S {C c; } structure statique C {}} 'appelant alors' mixin Foo!(); 'Puis j'obtiens le bloc indépendant de la commande, sans le support supplémentaire! =) – Tamas

+0

Eh bien, vous pouvez toujours changer le nom chaque fois que vous en créez un. Titulaire, Lynch, Mukasey, Gonzales :) ou Holder1, Holder2 peu importe. L'astuce __LINE__ peut vous aider à créer des noms uniques dans votre code de génération de chaîne mixin.Vous pouvez également essayer de créer un modèle 'mixin 'au lieu d'un' struct', puis le mélanger juste après la déclaration afin que ses symboles soient introduits dans la portée parent. –