digitalmars.D.learn - Subtyping with alias this
- novice3 (35/35) Aug 17 2020 Hello.
- H. S. Teoh (20/34) Aug 17 2020 What you need is to create an overload of toString that takes a
- novice3 (32/35) Aug 17 2020 Sorry, i can't make it works.
- H. S. Teoh (44/48) Aug 17 2020 Here's a working example:
- novice3 (2/3) Aug 17 2020 Thank you, it works!
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.
Aug 17 2020
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
Aug 17 2020
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)
Aug 17 2020
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!
Aug 17 2020
On Tuesday, 18 August 2020 at 05:54:16 UTC, H. S. Teoh wrote:Here's a working example:Thank you, it works!
Aug 17 2020