On Thursday, April 07, 2016 07:45:06 yawniek via Digitalmars-d-learn wrote: > what is the way one is supposed to parse e.g. a > double of unixtime (as delived by nginx logs) into a SysTime? > > currently i'm creating a wrapper struct around SysTime with alias > this as: > > https://gist.github.com/yannick/6caf5a5184beea0c24f35d9d4a4c7783 > > really ugly imho. > > is there a better way to do this?
Functions like format, to, etc. all use toString and constructors when dealing with conversions to and from string. There is no way to provide a custom conversion function for them to use with a type instead of what's built into the type. So, if you want this to be automatic as you pass the type around, then AFAIK, your solution is really the only solution. Certainly, you can create a custom conversion function and use it in your own code, but nothing else is going to know about it or use it. But honestly, I don't see how we even _could_ make it possible to provide a custom conversion function except for having another argument (either an alias template argument, or a function argument which is a delegate), and that would mean that everything that might use such a conversion function would have to accept it. That might work for something like std.conv.to, but once you're dealing with something like the CSVParser, what's it going to do? Have every function that might use such a conversion take a template argument for the conversion function so that it could pass it on to std.conv.to or std.conv.parse? And what of code that then uses CSVParser? Does it need to then accept and pass on such conversion functions? And what if you need more than one conversion function, because you're dealing with multiple types that you want to convert differently than normal? I just don't see how that scales. Really, as annoying as it may be to wrap the type in another type just to get the conversion, it's by far the cleanest way to do it. I just don't see how we even _could_ do in a sane way that involved any kind of free function. That would be like trying to arbitrarily add a constructor or overloaded operator to a type and have all other code magically use it, which is pretty much impossible given D's compilation model (e.g. the type could be being used in a library that was already compiled when you try and use it in your program), and how on earth would you deal with conflicts? If two different modules both tried to add a constructor or overloaded operator to a type, and those conflicted, how would other code know which to use - especially when this is supposed to be invisible to them? So, while I understand your frustration, I just don't see any other sane way to approach this problem than what you've done. Putting it all in a wrapper type encapsulates it in a way that it can actually work, whereas the other options get messy really fast if they're possible at all. - Jonathan M Davis
