Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
August 17, 2020 Subtyping with alias this | ||||
---|---|---|---|---|
| ||||
Hello. I need subtype uint to store ipv4 address. It should be like ordinary uint, except conversion to string with %s format. My try https://run.dlang.io/is/fwTc0H failed on last assert: ``` struct IpV4Address { private uint ip; alias ip this; string toString() { import std.conv: to; return to!string((ip >>> 24) & 0xFF) ~ "." ~ to!string((ip >>> 16) & 0xFF) ~ "." ~ to!string((ip >>> 8) & 0xFF) ~ "." ~ to!string(ip & 0xFF); } } void main() { import std.format: format; IpV4Address x; x = 0x01020304; // 1.2.3.4 assert( x == 0x01020304 ); assert( format("%s", x) == "1.2.3.4" ); assert( format("%x", x) == "01020304" ); // FAILED /+ std.format.FormatException@/dlang/dmd-nightly/linux/bin64/../../src/phobos/std/format.d(4065): Expected '%s' format specifier for type 'IpV4Address' +/ } ``` Is my goal (subtype should be normal uint, but with pretty to-string conversion) possible? Thanks. |
August 17, 2020 Re: Subtyping with alias this | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice3 | On Mon, Aug 17, 2020 at 02:29:47PM +0000, novice3 via Digitalmars-d-learn wrote: [...] > ``` > struct IpV4Address > { > private uint ip; > alias ip this; > > string toString() > { > import std.conv: to; > return to!string((ip >>> 24) & 0xFF) ~ "." ~ > to!string((ip >>> 16) & 0xFF) ~ "." ~ > to!string((ip >>> 8) & 0xFF) ~ "." ~ > to!string(ip & 0xFF); > } What you need is to create an overload of toString that takes a FormatSpec parameter, so that you can decide what should be output for which format spec. Something along these lines: string toString(W,Char)(W sink, FormatSpec!Char fmt) { if (fmt.spec == "s") return to!string((ip >>> 24) & 0xFF) ~ "." ~ to!string((ip >>> 16) & 0xFF) ~ "." ~ to!string((ip >>> 8) & 0xFF) ~ "." ~ to!string(ip & 0xFF); else // Fallback to usual uint-formatting return format("%s", ip); } T -- We've all heard that a million monkeys banging on a million typewriters will eventually reproduce the entire works of Shakespeare. Now, thanks to the Internet, we know this is not true. -- Robert Wilensk |
August 18, 2020 Re: Subtyping with alias this | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Monday, 17 August 2020 at 14:43:27 UTC, H. S. Teoh wrote: > What you need is to create an overload of toString that takes a FormatSpec parameter, so that you can decide what should be output for which format spec. Something along these lines: Sorry, i can't make it works. I tried ti read format.d, but it too complex for me. The problem is: if i use fmt.spec in overloaded toString(), when i get error "phobos/std/format.d(2243): Error: no property ip for type onlineapp.IpV4Address" reduced code https://run.dlang.io/is/Kgbhfd ``` import std.format; struct IpV4Address { private uint ip; alias ip this; void toString(W,Char)(W sink, FormatSpec!Char fmt) { sink(fmt.spec); // ERROR //sink("s"); // OK } } void main() { IpV4Address x; assert( format("%s", x) == "s"); } ``` /dlang/dmd-nightly/linux/bin64/../../src/phobos/std/format.d(2243): Error: no property ip for type onlineapp.IpV4Address /dlang/dmd-nightly/linux/bin64/../../src/phobos/std/format.d(1875): Error: template instance std.format.formatValueImpl!(Appender!string, IpV4Address, char) error instantiating /dlang/dmd-nightly/linux/bin64/../../src/phobos/std/format.d(576): instantiated from here: formatValue!(Appender!string, IpV4Address, char) /dlang/dmd-nightly/linux/bin64/../../src/phobos/std/format.d(6630): instantiated from here: formattedWrite!(Appender!string, char, IpV4Address) onlineapp.d(17): instantiated from here: format!(char, IpV4Address) |
August 17, 2020 Re: Subtyping with alias this | ||||
---|---|---|---|---|
| ||||
Posted in reply to novice3 | On Tue, Aug 18, 2020 at 05:34:58AM +0000, novice3 via Digitalmars-d-learn wrote: [...] > The problem is: > if i use fmt.spec in overloaded toString(), > when i get error "phobos/std/format.d(2243): Error: no property ip for > type onlineapp.IpV4Address" Here's a working example: --------------------------------------------- import std; struct IpV4Address { private uint ip; alias ip this; void toString(W,Char)(W sink, FormatSpec!Char fmt) { if (fmt.spec == 's') { // Deal with %s here sink.formattedWrite("%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF); } else { // Everything else formatValue(sink, this.ip, fmt); } } // This unittest is to workaround the sillyness that if toString // doesn't compile, std.format pretends it doesn't exist and/or // the compiler swallows the real error and substitutes it with // an irrelevant error that has nothing to do with the real // problem. unittest { IpV4Address ip; auto app = appender!string; ip.toString(app, FormatSpec!char.init); } } unittest { auto ip = IpV4Address(0x01020304); writefln("%s", ip); writefln("%x", ip); writefln("%d", ip); } --------------------------------------------- T -- No! I'm not in denial! |
August 18, 2020 Re: Subtyping with alias this | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Tuesday, 18 August 2020 at 05:54:16 UTC, H. S. Teoh wrote:
> Here's a working example:
Thank you, it works!
|
Copyright © 1999-2021 by the D Language Foundation