2017-10-19 19 views
1

Quelqu'un peut-il m'expliquer le comportement de ce qui suit?Comportement bizarre avec "ce T"

Avec une classe de base comme celui-ci:

abstract class Foo 
{ 
    string[] members; 

    final: 

    this(this T)(T child) 
    { 
     import std.conv : to; 

     foreach (member; __traits(derivedMembers, T)) 
     { 
      mixin("members ~= to!string(child." ~ member ~ ");\r\n"); 
     } 
    } 

    void printMembers() 
    { 
     writeln(members); 
    } 
} 

Je vous attendriez membres à avec les valeurs du type d'enfant adopté.

Cependant, le comportement est vraiment bizarre.

Les membres du tableau seront remplis à l'infini, ce qui entraînera la perte de mémoire du programme.

Si vous modifiez le mixin à ceci:

mixin("if (members.length < 20) members ~= to!string(child." ~ member ~ ");\r\n"); 

alors vous serez en mesure de voir comment est peuplé le tableau, mais les valeurs ne font pas de sens en termes de la façon dont le code devrait fonctionner.

Exemple d'utilisation:

class Bar : Foo 
{ 
    int baba; 
    int caca; 

    this() { baba = 1; caca = 2; super(this); } 
} 

class Baz : Foo 
{ 
    int foo; 
    int bar; 
    int baz; 

    this() { foo = 100; bar = 200; baz = 300; super(this); } 
} 

void main() 
{ 
    auto b = new Bar(); 
    auto a = new Baz(); 

    b.printMembers(); 
    a.printMembers(); 
    b.printMembers(); 
} 

Le code ci-dessus produira une sortie comme ci-dessous:

["1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "f193.Bar", "f193.Bar", "f193.Bar", "f193.Bar", "f193.Bar", "f193.Bar", "f193.Bar", "f193.Bar", "f193.Bar"] 
["100", "200", "300", "100", "200", "300", "100", "200", "300", "100", "200", "300", "100", "200", "300", "100", "200", "300", "100", "200", "f193.Baz", "f193.Baz", "f193.Baz", "f193.Baz", "f193.Baz", "f193.Baz"] 
["1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "f193.Bar", "f193.Bar", "f193.Bar", "f193.Bar", "f193.Bar", "f193.Bar", "f193.Bar", "f193.Bar", "f193.Bar"] 

Là où je me serais attendu à quelque chose comme:

["1", "2"] 
["100", "200", "300"] 
["1", "2"] 

Pourquoi exactement ce se comporter comme ça? Cela ressemble à un bug pour moi, mais peut-être y a-t-il une raison au comportement?

Répondre

1

En regardant le code, je vois que c'est parce que le constructeur est appelé récursif.

La solution simple est la suivante:

static if (member != "__ctor") mixin("members ~= to!string(child." ~ member ~ ");\r\n");