Is std.variant useful for types only known at run time?

jfondren julian.fondren at gmail.com
Wed Sep 8 08:39:53 UTC 2021


On Wednesday, 8 September 2021 at 07:10:21 UTC, Chris Piker wrote:
> Hi D
>
> I'm working on data streaming reading module where the encoding 
> of each input array isn't known until runtime.  For example 
> date-time column values may be encoded as:
>
>    * An ISO-8601 UTC time string (aka char[])
>    * A ASCII floating point value with an indicated unit size 
> and epoch (aka char[])
>    * A IEEE double with an indicated endianness, unit size, and 
> epoch. (aka double[])
>    * A 64-bit signed in with an indicated endianness, unit 
> size, and epoch. (aka long[])

a std.variant.Variant can contain *any* type, but this only four 
types, so I'd look at a std.sumtype of them first:

```d
import std.sumtype;

struct ISO8601 { }
struct FloatEpoch { }
struct DoubleEpoch { }
struct LongEpoch { }
alias Time = SumType!(ISO8601, FloatEpoch, DoubleEpoch, 
LongEpoch);

void main() {
     import std.stdio : writeln;
     import std.format : format;

     Time e = ISO8601();
     writeln(e.match!(
         (FloatEpoch _) => "doesn't happen",
         (DoubleEpoch _) => "doesn't happen",
         (LongEpoch _) => "an error to omit, unlike the next 
example",
         (ISO8601 time) => format!"%s"(time),
     ));
}
```

...

> I'm wondering if std.variant is useful in cases where type 
> information is only known at run-time, since many of the 
> flexible data structures I've run across so far in D require 
> compile-time information.

It is. It's used for message passing in std.concurrency for 
example, where an actor can receive any kind of type into its 
messagebox. If std.sumtype didn't exist then I might look at 
std.variant or a novel discriminated union of my own or OOP, 
where an option is to try casting to the different subtypes until 
the cast works:

```d
class Encoding { }
class ISO8601 : Encoding { }
class FloatEpoch : Encoding { }
class DoubleEpoch : Encoding { }
class LongEpoch : Encoding { }

void main() {
     import std.stdio : writeln;

     Encoding e = new ISO8601;
     if (!cast(FloatEpoch) e) writeln("it's null");
     if (!cast(LongEpoch) e) writeln("it's null");
     if (auto time = cast(ISO8601) e)
         writeln(time);
}
```


More information about the Digitalmars-d-learn mailing list