How to forward format specifiers ?
Element 126 via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sun Jun 29 04:55:38 PDT 2014
I am trying to define custom format specifiers (as described here [1])
for the following wrapper struct :
import std.stdio;
import std.format: formattedWrite, FormatSpec;
import std.string: format;
struct wrapper(T) {
private T val;
public this(T newVal) pure { val = newVal; }
public void toString(
scope void delegate(const(char)[]) sink,
FormatSpec!char fmt
) const
{
formattedWrite(sink, /+ Format string +/ , val);
}
}
unittest {
immutable uint base = 16;
auto a = wrapper!uint(base);
assert(format("%x", a) == format("%x", base));
assert(format("%08x", a) == format("%08x", base));
}
More precisely, I want to forward the format specifier fmt received by
wrapper!T.toString to formattedWrite.
Since formattedWrite expects a const(char)[] "string" as its second
argument, I first naively tried to use :
formattedWrite(sink, to!string(fmt), val);
but to!string(fmt) gives something similar to :
address = 7FFFE91C54C0
width = 0
precision = 2147483646
spec = x
indexStart = 0
indexEnd = 0
flDash = false
flZero = false
flSpace = false
flPlus = false
flHash = false
nested =
trailing =
instead of the original format string, thus causing toString to fail at
runtime.
The documentation for std.format [2] mentions a second prototype (among
four) for toString :
const void toString(
scope void delegate(const(char)[]) sink,
string fmt
);
So I tried to modify wrapper!T.toString as follows :
public void toString(
scope void delegate(const(char)[]) sink,
string fmt
) const
{
formattedWrite(sink, fmt, val);
}
but this one throws exception at runtime :
std.format.FormatException@/usr/include/dlang/dmd/std/format.d(2537):
Expected '%s' format specifier for type 'wrapper!uint'.
I can make it work for simple cases by manually creating the format
string using format() with the FormatSpec attributes, but this approach
is not generic and will fail for complex format strings.
I've certainly missed something, but I can't figure out what is the
right way to do it. What did I do wrong here ?
I remember having seen the "void toString(scope void delegate(/*...*/),
/*...*/) const" prototypes being deprecated, but I don't know where it
was. Maybe there is a better solution now ?
[1] http://wiki.dlang.org/Defining_custom_print_format_specifiers
[2] http://dlang.org/phobos-prerelease/std_format.html#.formatValue
More information about the Digitalmars-d-learn
mailing list