Thread overview
How to get a range from std.container.array for use with std.format.sformat?
Jan 30, 2018
cc
Jan 30, 2018
cc
Jan 30, 2018
Seb
January 30, 2018
	import std.container;
	import std.format;
	Array!char str;
	str.length = 256;

	str.sformat!"%s:%s"("some", "string");
	// Error: template std.format.sformat cannot deduce function from argument types !("%s:%s")(Array!char, string, string), candidates are:
	//   std.format.sformat(alias fmt, Args...)(char[] buf, Args args) if (isSomeString!(typeof(fmt)))
	//   std.format.sformat(Char, Args...)(char[] buf, in Char[] fmt, Args args)

	auto rng = cast(char[]) str[];
	// Error: cannot cast expression `str.opSlice()` of type `RangeT!(Array!char)` to `char[]`


Additionally, would sformat cause GC allocations even when writing to a preallocated buffer?
January 30, 2018
On 1/30/18 12:53 PM, cc wrote:
>      import std.container;
>      import std.format;
>      Array!char str;
>      str.length = 256;
> 
>      str.sformat!"%s:%s"("some", "string");
>      // Error: template std.format.sformat cannot deduce function from argument types !("%s:%s")(Array!char, string, string), candidates are:
>      //   std.format.sformat(alias fmt, Args...)(char[] buf, Args args) if (isSomeString!(typeof(fmt)))
>      //   std.format.sformat(Char, Args...)(char[] buf, in Char[] fmt, Args args)

sformat requires a builtin array, apparently. It doesn't work for other types.

> 
>      auto rng = cast(char[]) str[];
>      // Error: cannot cast expression `str.opSlice()` of type `RangeT!(Array!char)` to `char[]`

why not just auto rng = str[]?

> Additionally, would sformat cause GC allocations even when writing to a preallocated buffer?

Not directly. If sformat needs to call a function on what you are asking to format that would use the GC, then it would not be @nogc.

-Steve
January 30, 2018
Still doesn't work without the cast it seems..

	auto rng = str[];
	rng.sformat!"%s:%s"("some", "string");
	// Error: template std.format.sformat cannot deduce function from argument types !("%s:%s")(RangeT!(Array!char), string, string)
January 30, 2018
On Tuesday, 30 January 2018 at 18:42:45 UTC, Steven Schveighoffer wrote:
> On 1/30/18 12:53 PM, cc wrote:
>>      import std.container;
>>      import std.format;
>>      Array!char str;
>>      str.length = 256;
>> 
>>      str.sformat!"%s:%s"("some", "string");
>>      // Error: template std.format.sformat cannot deduce function from argument types !("%s:%s")(Array!char, string, string), candidates are:
>>      //   std.format.sformat(alias fmt, Args...)(char[] buf, Args args) if (isSomeString!(typeof(fmt)))
>>      //   std.format.sformat(Char, Args...)(char[] buf, in Char[] fmt, Args args)
>
> sformat requires a builtin array, apparently. It doesn't work for other types.

For everything else, you can use formattedWrite:


```
import std.array : appender;
auto writer = appender!string();
writer.formattedWrite!"%s is the ultimate %s."(42, "answer");
writeln(writer.data);
```

without any GC:

```
/+dub.sdl:
dependency "emsi_containers" version="~>0.6.0"
+/
import std.format, std.stdio;

void main()
{
    import containers;
    DynamicArray!char arr;
    arr.formattedWrite!"%s is the ultimate %s."(42, "answer");
    printf("%.*s\n", arr.length, arr.ptr);
}
```

https://run.dlang.io/is/Taem9j
January 31, 2018
On 1/30/18 2:19 PM, cc wrote:
> Still doesn't work without the cast it seems..
> 
>      auto rng = str[];
>      rng.sformat!"%s:%s"("some", "string");
>      // Error: template std.format.sformat cannot deduce function from argument types !("%s:%s")(RangeT!(Array!char), string, string)

I misunderstood what you were trying to do. I thought you were just trying to get a valid range, missed the requirement that the range works with sformat (obviously from the subject! sorry).

Indeed, there isn't a way to extract an actual char[] from Array (and this is intentional).

But as Seb says, you can use formattedWrite:

auto rng = str[];
rng.formattedWrite("%s:%s", "some", "string");

-Steve