On 09/02/2011 12:09 AM, Damian Ziemba wrote:
On Thu, 01 Sep 2011 13:59:29 +0200, Timon Gehr wrote:

static assert(isInputRange!Test);
static assert(isInputRange!Test2);

toString is not shadowed, but the implementation of writeln assumes that
your types are an InputRange (they provide, by the means of opDispatch,
front(), empty() and popFront())

The fact that writeln([]); prints a new line instead of "[]" is a bug
that has already been taken care of in a pull request afaik.

This specific problem can be solved by making your types not follow the
InputRange interface, by putting an appropriate constraint on your
opDispatch.


import std.stdio;

struct Test
{
        string opDispatch( string key )() if(key!="popFront") {
                return "I am dispatching in struct!";
        }

        string toString()
        {
                return "I am Test struct!";
        }
}

class Test2
{
        string opDispatch( string key )() if(key!="popFront") {
                return "I am dispatching in class!";
        }

        string toString()
        {
                return "I am Test class!";
        }
}

void main()
{
        Test test = Test();
        writeln ( test.s ); // I am dispatching in struct! writeln
( test.s()
        ); // I am dispatching in struct! writeln ( test ); //I am Test
struct!
        
        Test2 test2 = new Test2();
        writeln ( test2.s ); // I am dispatching in class! writeln
( test2.s()
        ); // I am dispatching in class! writeln ( test2 ); // I am Test
class!
}

Yes, this fix the problem.

Hmm, after all its a bit loose of a keyword, becouse I can't use anymore
test.popFront. For example if class acts as a storage device

class Storage
{
        string[ string ] vars;

        string opDispatch( string key )() if ( key != "popFront" )
        {
                if ( key in vars ) return vars[ key ];
                else return "";
        }

        string toString() { // implement me
        }
}

auto storage = new Storage;
storage.vars["test"] = "I'm a test!";
storage.vars["popFront"] = "I'm a poping around! :D";

writeln( storage.test ); // I'm a test!
writeln( storage.popFront ); // error

Ofcours, in opDispatch I can use empty or front instead of popFront but
it is still loose of one keyword.

Looks like it's a loose I have to take :-)

Thank you very much for reply!

Best regards,
Damian Ziemba

template isInputRange(R)
{
    enum bool isInputRange = is(typeof(
    {
        R r;              // can define a range object
        if (r.empty) {}   // can test for empty
        r.popFront();     // can invoke popFront()
        auto h = r.front; // can get the front of the range
    }()));
}

With the next DMD release, you could use a struct with a disabled default constructor. Because it cannot be defined, the first line will fail, and isInputRange will be false.

Basically, anything that will make

        R r;              // can define a range object
        if (r.empty) {}   // can test for empty
        r.popFront();     // can invoke popFront()
        auto h = r.front; // can get the front of the range

fail to compile is good enough. Eg, if r.empty is not convertible to bool.







Reply via email to