opDispatch shadowing toString - feature or bug?

Timon Gehr timon.gehr at gmx.ch
Thu Sep 1 15:58:02 PDT 2011


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.









More information about the Digitalmars-d-learn mailing list