Thread overview
Output Range Problem? How to make it work?
6 days ago
apz28
6 days ago
Paul Backus
6 days ago
apz28
6 days ago
Paul Backus
6 days ago

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)
*/

6 days ago

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:

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:

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

6 days ago

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:

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:

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

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)
*/

6 days ago

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:

Dest convert(Source, Dest)(Source source)
{
    return cast(Dest) source;
}

void main()
{
    double d = 123.456;
    auto result = convert(d); // Source = double, Dest = ???
}