www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Output Range Problem? How to make it work?

reply apz28 <home home.com> writes:
import std.range.primitives: isOutputRange;

      safe:

     struct Buffer
     {
      safe:

         void put(char c)
     	{}
         void put(scope const(char)[] s)
         {}
     }

     struct Foo
     {
      safe:

         string toString()
     	{return null;}

         ref Writer toString(Writer, Char)(return ref Writer sink)
         if (isOutputRange!(Writer, Char) && isSomeChar!Char)
         {return sink;}

         string toString(const(char)[] fmt)
         {return null;}
     }

     void main()
     {	
         Buffer buffer;
         Foo foo;
         foo.toString(buffer);
     }


/* Getting this error
onlineapp.d(34): Error: none of the overloads of `toString` are 
callable using argument types `(Buffer)`, candidates are:
onlineapp.d(19):        `onlineapp.Foo.toString()`
onlineapp.d(26):        `onlineapp.Foo.toString(const(char)[] 
fmt)`
onlineapp.d(22):        `toString(Writer, Char)(return ref Writer 
sink)`
*/
Oct 10 2021
parent reply Paul Backus <snarwin gmail.com> writes:
On Monday, 11 October 2021 at 00:19:44 UTC, apz28 wrote:
 /* Getting this error
 onlineapp.d(34): Error: none of the overloads of `toString` are 
 callable using argument types `(Buffer)`, candidates are:
 onlineapp.d(19):        `onlineapp.Foo.toString()`
 onlineapp.d(26):        `onlineapp.Foo.toString(const(char)[] 
 fmt)`
 onlineapp.d(22):        `toString(Writer, Char)(return ref 
 Writer sink)`
 */
The signature of your `toString` method should match one of the examples in [the documentation][1]: ```d void toString(Writer, Char)(ref Writer w, const ref FormatSpec!Char fmt) void toString(Writer)(ref Writer w) string toString(); ``` Here is an example that works: ```d import std.range: put; import std.array: appender; import std.format: formattedWrite; struct Foo { void toString(Writer)(ref Writer writer) { put(writer, "Foo"); } } void main() { auto buffer = appender!string; Foo foo; formattedWrite(buffer, "%s", foo); assert(buffer[] == "Foo"); } ``` Link: https://run.dlang.io/is/dZLRuo [1]: https://phobos.dpldocs.info/std.format.write.html
Oct 10 2021
parent reply apz28 <home home.com> writes:
On Monday, 11 October 2021 at 00:37:43 UTC, Paul Backus wrote:
 On Monday, 11 October 2021 at 00:19:44 UTC, apz28 wrote:
 /* Getting this error
 onlineapp.d(34): Error: none of the overloads of `toString` 
 are callable using argument types `(Buffer)`, candidates are:
 onlineapp.d(19):        `onlineapp.Foo.toString()`
 onlineapp.d(26):        `onlineapp.Foo.toString(const(char)[] 
 fmt)`
 onlineapp.d(22):        `toString(Writer, Char)(return ref 
 Writer sink)`
 */
The signature of your `toString` method should match one of the examples in [the documentation][1]: ```d void toString(Writer, Char)(ref Writer w, const ref FormatSpec!Char fmt) void toString(Writer)(ref Writer w) string toString(); ``` Here is an example that works: ```d import std.range: put; import std.array: appender; import std.format: formattedWrite; struct Foo { void toString(Writer)(ref Writer writer) { put(writer, "Foo"); } } void main() { auto buffer = appender!string; Foo foo; formattedWrite(buffer, "%s", foo); assert(buffer[] == "Foo"); } ``` Link: https://run.dlang.io/is/dZLRuo [1]: https://phobos.dpldocs.info/std.format.write.html
On Monday, 11 October 2021 at 00:37:43 UTC, Paul Backus wrote: The subject is why the call is not allowed (format is not mention in question). Below sample is a bit more clear import std.range.primitives : isOutputRange; import std.traits: isSomeChar; safe: struct Buffer(Char) { safe: void put(Char c) {} void put(scope const(Char)[] s) {} } struct Foo { safe: ref Writer outWork(Writer)(return ref Writer sink) if (isOutputRange!(Writer, char)) {return sink;} // Remove " && isSomeChar!Char" does not make any difference ref Writer outFail(Writer, Char)(return ref Writer sink) if (isOutputRange!(Writer, Char) && isSomeChar!Char) {return sink;} } void main() { pragma(msg, isOutputRange!(Buffer!char, char)); // Print true Buffer!char buffer; Foo foo; foo.outWork(buffer); // OK foo.outFail!(Buffer!char, char)(buffer); // OK with explicit foo.outFail(buffer); // NOT OK } /* Blow is output from online compiler true onlineapp.d(40): Error: template `onlineapp.Foo.outFail` cannot deduce function from argument types `!()(Buffer!char)`, candidates are: onlineapp.d(25): `outFail(Writer, Char)(return ref Writer sink)` */
Oct 11 2021
parent Paul Backus <snarwin gmail.com> writes:
On Monday, 11 October 2021 at 15:57:00 UTC, apz28 wrote:
 The subject is why the call is not allowed (format is not 
 mention in question). Below sample is a bit more clear
[...]
         ref Writer outFail(Writer, Char)(return ref Writer sink)
         if (isOutputRange!(Writer, Char) && isSomeChar!Char)
         {return sink;}
[...]
         foo.outFail(buffer); // NOT OK
The template parameter `Char` does not appear anywhere in the function's parameter list, so the compiler cannot deduce it from the function's arguments. Here is a simpler example that demonstrates the same problem: ```d Dest convert(Source, Dest)(Source source) { return cast(Dest) source; } void main() { double d = 123.456; auto result = convert(d); // Source = double, Dest = ??? } ```
Oct 11 2021