write, toString, formatValue & range interface
Robert Jacques
sandford at jhu.edu
Tue Dec 14 06:35:20 PST 2010
On Tue, 14 Dec 2010 05:02:41 -0500, spir <denis.spir at gmail.com> wrote:
> Hello,
>
>
> Had a nice time degugging an issue after having added an input range
> interface to a (big) struct type. Finally managed to deduce the problem
> happens when writing out an element of the struct type. This introduced
> an infinite loop ending in segfault. Found it weird because the struct's
> toString does not iterate over the type, so there was no reason to use
> the range interface.
> This is why I guessed toString was not called. And in fact, forcing its
> use by explicitely calling .toString() solved the bug! 2 correspondants
> (Stephan Mueller & Ivan Melnychuk) helped me by pointing to the various
> template-selection criteria of formatValue.
>
>
>
> There seems to be a pair of bugs in the set of formatValue templates
> constaints, which cause the following problems:
> * If a class defines both toString and a range interface, compiler error
> (additional bug pointed by Stephan Mueller).
> * For structs, the presence of a range interface shortcuts toString.
> * If a range outputs elements of the same type, writing (and probably
> other features) runs into an infinite loop. This case is unchecked yet.
>
>
>
> The following changes may, I guess, solve the first two problems:
> (1) structs added (with classes) to the template selecting the use of
> toString
> (2) the template that selects the use of ranges checks there is no
> toString
> (3) the special case of using t.stringof for stucts must be selected
> only in last resort -- actually, this case may be suppressed and
> integrated into the general class/struct case.
>
> This means changing the following formatValue templates (quickly
> written, absolutely untested ;-):
>
> // case use toString (or struct .stringof): add structs
> void formatValue(Writer, T, Char)(Writer w, T val, ref FormatSpec!Char f)
> if (is(T == class) || is(T == struct))
> {
> // in case of struct, detect whether toString is defined, else use
> T.stringof
> }
>
> // case use range interface: check no toString available
> // also add a test that the range does not output elements of the same
> type!!!
> void formatValue(Writer, T, Char)(Writer w, T val,
> ref FormatSpec!Char f)
> if (
> isInputRange!T && !isSomeChar!(ElementType!T) ||
> ! is(typeof(val.toString() == string))
> )
> {...}
>
> // special case use T.stringof for struct: useless? (else check no
> toString)
> void formatValue(Writer, T, Char)(Writer w, T val,
> ref FormatSpec!Char f)
> if (
> is(T == struct) && !isInputRange!T &&
> ! is(typeof(val.toString() == string))
> )
> {
> put(w, T.stringof);
> }
>
>
>
> Also, (1) the online doc of std.format seems outdated, no constraint for
> instance (2) the in-source doc is rather confusing, several comments do
> not describe the following code.
>
>
>
> Hope this helps,
> Denis
> -- -- -- -- -- -- --
> vit esse estrany ☣
>
> spir.wikidot.com
>
Having recently run into this without knowing it, vote++. Also, please
file a bug report (or two).
More information about the Digitalmars-d
mailing list