[Issue 5233] [patch] std.range.put accepts *any* element type when putting to an array.

d-bugmail at puremagic.com d-bugmail at puremagic.com
Fri Apr 1 22:04:50 PDT 2011


http://d.puremagic.com/issues/show_bug.cgi?id=5233



--- Comment #4 from Rob Jacques <sandford at jhu.edu> 2011-04-01 22:01:14 PDT ---
Patch version 5.
*** API Addition ***
Optional template boolean parameter asArray. If true, put bypasses testing
r.put(e), r.put(e[]), r(e) and r(e[]). This allows templated user defined put
routines to accept all valid put types without duplicating all of put's
transforms/code snippets. For example:

struct Stack(T) {
    put(U item) if( isOutputRange!(T[],U) ) {
        static if( is(U:T) ) {
            // put one item onto the stack
        } else {
            .put!(typeof(this),U,true)(this,item);
        }
    }
}

* Updated documentation to reflect changes
* Removal of all static asserts. static asserts do not currently compose well
with is(typeof(...)) / __traits(compiles,...) statements. Instead, the error
message is left as a single line statement. This causes a normal compilation
error with a reasonable error message, since the error info is embedded in the
bad string, the value of which is included in the error message.
* All string put string and string put char cases are UTF correct.
* The r(e) snippet now filters out types with ctors but not opCall.
* Support was added for index only and foreach-able E types.
* Simplification of snippets and code layout


[Patch]

/** Outputs $(D e) to $(D r). The exact effect is dependent upon the two types.
    Several cases are accepted, as described below. The code snippets are
    attempted in order, and the first to compile "wins" and gets evaluated.
    Setting asArray to true will skip code snippets using user defined
    $(D put) and opCall methods, allowing templated user defined $(D put)
    methods to reuse some of $(D put)'s code snippets.

$(BOOKTABLE ,

$(TR $(TH Code Snippet) $(TH Scenario))

$(TR $(TD $(D isSomeString!R && isSomeString!E ))
     $(TD $(D R) is a mutable string and $(D E) is a string.))

$(TR $(TD $(D isSomeString!R && isSomeChar!E ))
     $(TD $(D R) is a mutable string and $(D E) is a character.))

$(TR $(TD $(D r.put(e);))
     $(TD $(D R) defines a method $(D put) accepting an $(D E).))

$(TR $(TD $(D r.put([ e ]);))
     $(TD $(D R) defines a method $(D put) accepting an $(D E[]).))

$(TR $(TD $(D r.front = e; r.popFront();))
     $(TD $(D R) is an input range and $(D e) is assignable to $(D r.front).))

$(TR $(TD $(D foreach(v; e) put(r,v)))
     $(TD Copying range $(D E) to range $(D R).))

$(TR $(TD $(D foreach(i;0..e.length) put(r,e[i])))
     $(TD Copying range $(D E) to range $(D R).))

$(TR $(TD $(D r(e);))
     $(TD $(D R) is e.g. a delegate accepting an $(D E).))

$(TR $(TD $(D r([ e ]);))
     $(TD $(D R) is e.g. a $(D delegate) accepting an $(D E[]).))

)
 */

void put(R, E, bool asArray = isArray!R )(ref R r, E e) {
    static if(isSomeString!R && isSomeString!E && is(typeof(r[0]=r[0])) ){
        static if( (typeof(r[0])).sizeof != E.sizeof ) {
            foreach( typeof(r[0]) v; e)
                put(r,v);
        } else {
            assert(e.length <= r.length);
            r[0..e.length] = e[];
            r = r[e.length..$];
        }
    } else static if(isSomeString!R && isSomeChar!E && is(typeof(r[0]=r[0])) ){
        static if( (typeof(r[0])).sizeof < E.sizeof ) {
            // Transcoding is required to support char[].put(dchar)
            typeof(r[0])[(typeof(r[0])).sizeof == 1 ? 4 : 2] encoded;
            auto len = std.utf.encode(encoded, e);
            put(r,encoded[0 .. len]);
        } else {
            assert(!r.empty);
            r[0] = e;
            r = r[1..$];
        }
    } else static if( !asArray && __traits(compiles,  r.put(  e          ))  ){
                                                      r.put(  e          );
    } else static if( !asArray && __traits(compiles,  r.put((&e)[0..1]   ))  ){
                                                      r.put((&e)[0..1]   );
    } else static if (isInputRange!R && is(typeof(r.front = e) )) {
        r.front = e;
        r.popFront();
    } else static if(__traits(compiles,{foreach(v; e)          put(r,  v );})){
                                        foreach(v; e)          put(r,  v );
    } else static if(__traits(compiles,{foreach(i;0..e.length) put(r,e[i]);})){
                                        foreach(i;0..e.length) put(r,e[i]);
    } else static if( _putCall!(R,E,asArray) && is(typeof( r( e          )) )){
                                                           r( e          );
    } else static if( _putCall!(R,E,asArray) && is(typeof( r( (&e)[0..1] )) )){
                                                           r( (&e)[0..1] );
    } else {
        // @@@BUG@@@ Static asserts can't be combined with is(typeof(put(r,e)))
        "Can't put a "~E.stringof~" into a "~R.stringof;
    }
}

// Helper template for put(): filters out opCall from ctors
private template _putCall(R, E, bool asArray = false) {
    static if(asArray)    enum _putCall = false;
    else static if( is(R==class) || is(R==struct) || is(R==union) )
         enum _putCall = is(typeof( (R r, E e){r.opCall(   e        );}))||
                         is(typeof( (R r, E e){r.opCall( (&e)[0..1] );}));
    else enum _putCall = is(typeof( (R r, E e){r(          e        );}))||
                         is(typeof( (R r, E e){r(        (&e)[0..1] );}));
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list