Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 1568

Show
Ignore:
Timestamp:
05/29/10 17:24:14 (15 years ago)
Author:
Masahiro Nakagawa
Message:

Remove tie. This implementation is unsafe!

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/docsrc/changelog.dd

    r1566 r1568  
    11Ddoc 
    22 
    33$(D_S D Change Log, 
    44 
    55 
    66$(VERSION 047, May 9, 2010, =================================================, 
    77 
    88    $(WHATSNEW 
    99    $(LI std.functional: toDelegate now accepts callable(function pointers, delegates and objects implement opCall) ) 
    1010    $(LI std.traits: Added templates to get compile-time information about functions.) 
    11     $(LI std.typecons: Added tie and AutoImplement.) 
     11    $(LI std.typecons: Added AutoImplement.) 
    1212    ) 
    1313    $(BUGSFIXED 
    1414    $(LI $(BUGZILLA 2738): Rebindable should work for interfaces.) 
    1515    $(LI $(BUGZILLA 2835): std.socket.TcpSocket doesn't actually connect) 
    1616    $(LI $(BUGZILLA 3088): std.xml.check() fails on xml comments) 
    1717    $(LI $(BUGZILLA 3200): std.xml doesn't follow spec for Tag.text) 
    1818    $(LI $(BUGZILLA 3465): isIdeographic can be wrong in std.xml) 
    1919    $(LI $(BUGZILLA 3653): Problem sorting array of Rebindable) 
    2020    $(LI $(BUGZILLA 3786): bug in std.string.removechars) 
    2121    $(LI $(BUGZILLA 3873): std.range.repeat should have popBack defined) 
  • trunk/phobos/std/typecons.d

    r1563 r1568  
    4141    // rebind r to refer to another object 
    4242    r = w2; 
    4343} 
    4444---- 
    4545 
    4646Copyright: Copyright Andrei Alexandrescu 2008 - 2009. 
    4747License:   <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>. 
    4848Authors:   $(WEB erdani.org, Andrei Alexandrescu), 
    4949           $(WEB bartoszmilewski.wordpress.com, Bartosz Milewski), 
    5050           Don Clugston, 
    51            Masahiro Nakagawa, 
    5251           Shin Fujishiro 
    5352 
    5453         Copyright Andrei Alexandrescu 2008 - 2009. 
    5554Distributed under the Boost Software License, Version 1.0. 
    5655   (See accompanying file LICENSE_1_0.txt or copy at 
    5756         http://www.boost.org/LICENSE_1_0.txt) 
    5857*/ 
    5958module std.typecons; 
    6059import std.array, std.contracts, std.conv, std.metastrings, std.traits, std.typetuple; 
    6160 
     
    512511assert(value.field[1] == 6.7); 
    513512assert(value.field[2] == "hello"); 
    514513---- 
    515514*/ 
    516515 
    517516Tuple!(T) tuple(T...)(T args) 
    518517{ 
    519518    typeof(return) result; 
    520519    static if (T.length > 0) result.field = args; 
    521520    return result; 
    522 } 
    523  
    524  
    525 /** 
    526  * $(D Ignore) represents a ignored element. 
    527  */ 
    528 struct Ignore {} 
    529 immutable Ignore ignore; 
    530  
    531  
    532 /** 
    533  * $(D Tie) binds some variables for tuple unpacking 
    534  * 
    535  * This struct is a internal implementation. Please use $(D tie) function. 
    536  * 
    537  * Example: 
    538  * ----- 
    539  * int    n; 
    540  * double d; 
    541  * 
    542  * tie(n, d) = tuple(10, 3.14); 
    543  * 
    544  * assert(n == 10); 
    545  * assert(d == 3.14); 
    546  * ----- 
    547  * 
    548  * $(D Tie) can be nested. 'ignore' is used for ignoring assignment. 
    549  * 
    550  * Example: 
    551  * ----- 
    552  * ubyte  n; 
    553  * double d; 
    554  * string s; 
    555  * 
    556  * tie(ignore, tie(d, s)) = tuple(true, tuple(1.4142, "Hi!")); 
    557  * 
    558  * assert(n == 0); 
    559  * assert(d == 1.4142); 
    560  * assert(s == "Hi!"); 
    561  * ----- 
    562  * 
    563  * $(D Tie) supports user-defined type. User-defined type needs to implement $(D opTie) method. 
    564  * 
    565  * Example: 
    566  * ----- 
    567  * struct S 
    568  * { 
    569  *     uint n; double d; 
    570  * 
    571  *     void opTie(U...)(ref Tie!U tie) 
    572  *     { 
    573  *         tie = tuple(n, d); 
    574  *     } 
    575  * } 
    576  * 
    577  * auto   s = S(10, 3.14); 
    578  * uint   n; 
    579  * double d; 
    580  * 
    581  * tie(n, d) = s; 
    582  * 
    583  * assert(n == 10); 
    584  * assert(d == 3.14); 
    585  * ----- 
    586  */ 
    587 struct Tie(Types...) if (Types.length > 1) 
    588 { 
    589   private: 
    590     template toAssignable(U) 
    591     { 
    592         static if (isPointer!(U) || isTie!(U) || is(U == typeof(ignore))) 
    593             alias U toAssignable; 
    594         else 
    595             alias U* toAssignable; 
    596     } 
    597  
    598     alias staticMap!(toAssignable, Types) T; 
    599  
    600     T captures_;  // references to variables 
    601  
    602  
    603   public: 
    604     /** 
    605      * Constructs a $(D Tie) with $(D_PARAM variables) argument. 
    606      * 
    607      * Params: 
    608      *  variables = a tuple to bind. 
    609      */ 
    610     this(ref Types variables) 
    611     { 
    612         foreach (i, variable; variables) { 
    613             static if (is(typeof(variable) == typeof(ignore))) {}      // ignore 
    614                 // do nothing 
    615             else static if (isPointer!(Types[i]) || isTie!(Types[i]))  // pointer, nested tie 
    616                 captures_[i] = variables[i]; 
    617             else                                                       // basic types 
    618                 captures_[i] = &variables[i]; 
    619         } 
    620     } 
    621  
    622  
    623     /** 
    624      * Assignment from $(D_PARAM rhs). 
    625      * 
    626      * Params: 
    627      *  rhs = Tuple, Tie, or User-defined type to assign. 
    628      * 
    629      * Returns: 
    630      *  this for chaining. 
    631      */ 
    632     Tie!Types opAssign(U)(auto ref U rhs) 
    633     { 
    634         static if (is(U X == Tuple!(W), W...)) 
    635             assignTuple(rhs); 
    636         else static if (__traits(compiles, rhs.opTie)) 
    637             rhs.opTie(this); 
    638         else static if (is(U == Tie) && __traits(isRef, rhs))  // nested 
    639             this.tupleof = rhs.tupleof; 
    640         else static if (is(U X == Tie!(W), W...))              // chain 
    641             assignTie(rhs); 
    642         else 
    643             static assert(false, "Unsupported type: " ~ U.stringof); 
    644  
    645         return this; 
    646     } 
    647  
    648  
    649   private: 
    650     void assignTuple(U...)(ref Tuple!U rhs) 
    651     { 
    652         static if (isMatching!U) { 
    653             foreach (i, capture; captures_) { 
    654                 static if (isPointer!(T[i]))                  // capture 
    655                     *captures_[i] = rhs.field[i]; 
    656                 else static if (is(T[i] V == Tie!(W), W...))  // nested 
    657                     capture = rhs.field[i]; 
    658             } 
    659         } else { 
    660             static assert(false, "Tuple contents are mismatched"); 
    661         } 
    662     } 
    663  
    664  
    665     void assignTie(U...)(ref Tie!U rhs) 
    666     { 
    667         static if (isMatching!U) { 
    668             foreach (i, capture; captures_) { 
    669                 static if (isPointer!(T[i]))                  // capture 
    670                     *captures_[i] = *rhs.captures_[i]; 
    671                 else static if (is(T[i] V == Tie!(W), W...))  // nested 
    672                     capture.assignTie(rhs.captures_[i]); 
    673             } 
    674         } else { 
    675             static assert(false, "Tie contents are mismatched"); 
    676         } 
    677     } 
    678  
    679  
    680     template isMatching(U...) 
    681     { 
    682         static if (T.length == U.length) 
    683             enum isMatching = verify!(0, U).result; 
    684         else 
    685             enum isMatching = false; 
    686     } 
    687  
    688  
    689     /* 
    690      * Verifies each element. 
    691      */ 
    692     template verify(uint I, U...) 
    693     { 
    694         static assert(T.length == I + U.length, "Caluculation failure"); 
    695  
    696         static if (U.length == 0) { 
    697             enum result = true; 
    698         } else { 
    699             alias T[I] Lhs; 
    700             alias U[0] Rhs; 
    701  
    702             static if (is(Lhs == typeof(ignore)))                     // ignore 
    703                 enum result = true && verify!(I + 1, U[1..$]).result; 
    704             else static if (isImplicitlyConvertible!(Rhs, Types[I]))  // capture 
    705                 enum result = true && verify!(I + 1, U[1..$]).result; 
    706             else static if (isTie!Lhs && isTuple!Rhs)                 // nested 
    707                 enum result = true && verify!(I + 1, U[1..$]).result; 
    708             else 
    709                 enum result = false; 
    710         } 
    711     } 
    712 } 
    713  
    714  
    715 /** 
    716  * Binds $(D_PARAM variables) using $(D Tie). 
    717  * 
    718  * Params: 
    719  *  variables = the contents to bind. 
    720  * 
    721  * Returns: 
    722  *  a $(D Tie) object binds $(D_PARAM variables). 
    723  */ 
    724 Tie!(T) tie(T...)(auto ref T variables) 
    725 { 
    726     return typeof(return)(variables); 
    727 } 
    728  
    729  
    730 /** 
    731  * Detects whether T is a $(D Tie) type. 
    732  */ 
    733 private template isTie(T) 
    734 { 
    735     enum isTie = __traits(compiles, { void f(X...)(Tie!X x) {}; f(T.init); }); 
    736 } 
    737  
    738  
    739 /** 
    740  * Detects whether T is a $(D Tuple) type. 
    741  */ 
    742 private template isTuple(T) 
    743 { 
    744     enum isTuple = __traits(compiles, { void f(X...)(Tuple!X x) {}; f(T.init); }); 
    745 } 
    746  
    747  
    748 unittest 
    749 { 
    750     { // capture 
    751         int    n; 
    752         double d; 
    753  
    754         tie(n, d) = tuple(20, 1.4142); 
    755  
    756         assert(n == 20); 
    757         assert(d == 1.4142); 
    758     } 
    759     { // ignore 
    760         ulong  n = 10; 
    761         double d = 3.14; 
    762  
    763         tie(n, ignore) = tuple(20, 1.4142); 
    764          
    765         assert(n == 20); 
    766         assert(d == 3.14); 
    767  
    768         tie(ignore, d) = tuple(20, 1.4142); 
    769          
    770         assert(n == 20); 
    771         assert(d == 1.4142); 
    772     } 
    773     { // nested 
    774         ubyte  n; 
    775         double d; 
    776         string s; 
    777  
    778         tie(n, tie(d, s)) = tuple(true, tuple(1.4142, "Hi!")); 
    779  
    780         assert(n == 1); 
    781         assert(d == 1.4142); 
    782         assert(s == "Hi!"); 
    783     } 
    784     { // chain 
    785         ulong  a, b; 
    786         real   c, d; 
    787         string e, f; 
    788  
    789         tie(a, tie(c, e)) = tie(b, tie(d, f)) = tuple(9, tuple(1.4142L, "Hi!")); 
    790  
    791         assert(a == 9); 
    792         assert(b == 9); 
    793         assert(c == 1.4142L); 
    794         assert(d == 1.4142L); 
    795         assert(e == "Hi!"); 
    796         assert(f == "Hi!"); 
    797     } 
    798     { // user-defined type 
    799         static class C 
    800         { 
    801             int n_; double d_; 
    802  
    803             this(int n, double d) 
    804             {  
    805                 n_ = n; 
    806                 d_ = d; 
    807             } 
    808  
    809             void opTie(U...)(ref Tie!U tie) 
    810             { 
    811                 tie = tuple(n_, d_); 
    812             } 
    813         } 
    814  
    815         auto   c = new C(10, 3.14); 
    816         int    n; 
    817         double d; 
    818  
    819         tie(n, d) = c; 
    820          
    821         assert(n == 10); 
    822         assert(d == 3.14); 
    823     } 
    824521} 
    825522 
    826523 
    827524private template enumValuesImpl(string name, BaseType, long index, T...) 
    828525{ 
    829526    static if (name.length) 
    830527    { 
    831528        enum string enumValuesImpl = "enum "~name~" : "~BaseType.stringof 
    832529            ~" { "~enumValuesImpl!("", BaseType, index, T)~"}\n"; 
    833530    }