2010-06-15 13 views
7

comment puis-je rendre une classe utilisable dans une instruction foreach?Comment rendre un objet (classe) joignable en D?

La classe contient un tableau associatif (par exemple, string [chaîne]). L'instruction foreach utilise donc ce tableau comme source.

donc ce que je veux:

auto obj = new Obj(); 
foreach (key, value; obj) 
{ 
    ... 
} 

Dois-je mettre en œuvre une someting d'interface comme ça?

EDIT:

La solution:

public int opApply(int delegate(ref string, ref Type) dg) 
{ 
    int result = 0; 

    foreach (ref key, ref value; data) 
    { 
     result = dg(key, value); 
     if (result != 0) 
     { 
      break; 
     } 
    } 

    return result; 
} 

Même chose pour le public int opApply (int délégué (ref Type) octies).

Répondre

4

D1:

class Foo 
{ 
    uint array[2]; 

    int opApply(int delegate(ref uint) dg) 
    { 
     int result = 0; 

     for (int i = 0; i < array.length; i++) 
     { 
      result = dg(array[i]); 
      if (result) 
       break; 
     } 
     return result; 
    } 
} 

D2:

itération sur les objets struct et de classe peut être fait avec les plages, ce qui signifie [un ensemble de] propriétés doivent être définies:

+2

Je ne pense pas que les gammes axé sur le soutien de foreach déballer encore. Et 'opApply' peut également être utilisé dans D2. – kennytm

+0

opApply était la solution, thnx! – VDVLeon

2

La solution affichée par l'OP est une solution valide, mais dans D2 il y en a une autre avec un ensemble différent de compromis. L'itération dans D peut être divisée en itération interne, gérée par opApply, et itération externe, gérée par des plages.

L'itération interne permet à l'objet itéré de contrôler la pile d'appels. Cela permet, par exemple, à la récursion d'être utilisée par l'objet itéré sans maintenir une pile explicite, mais rend impossible l'itération sur plusieurs structures en mode lockstep. L'itération externe fait le contraire.

L'itération externe est réalisée via des plages. Une plage est une classe ou une structure qui définit trois méthodes: front() donne accès au premier élément de la plage, popFront() avance la plage et empty() renvoie true si la plage est vide. Si la plage est infinie, vide peut être déclaré comme constante au lieu d'une fonction membre. De cette façon, l'appelant a le contrôle sur la pile d'appels, ce qui est un compromis qui peut être bon ou mauvais selon la situation.

Voici un exemple de l'utilisation de gammes pour l'itération:

/**This struct lazily produces all Fibonacci numbers.*/ 
struct Fibonacci { 
    ulong num1 = 0; 
    ulong num2 = 1; 

    ulong front() { 
     return num1 + num2; 
    } 

    void popFront() { 
     auto newNum2 = num1 + num2; 
     num1 = num2; 
     num2 = newNum2; 
    } 

    // A range of Fibonacci numbers is infinite. 
    enum bool empty = false; 
} 
+0

Donc, y a-t-il une réécriture du compilateur pour 'foreach (clé, valeur; collection)' en termes de primitives Range? Je n'ai encore rien vu, j'espère juste: D – Tim