Template type reduction

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Aug 16 10:26:28 PDT 2016


On 8/16/16 12:33 AM, Engine Machine wrote:
> On Monday, 15 August 2016 at 19:40:37 UTC, Steven Schveighoffer wrote:
>> On 8/15/16 3:31 PM, Engine Machine wrote:
>>> Suppose I have a templated type like
>>>
>>> struct S(T) { int x; static if (T is Y) int y; }
>>>
>>> I would like to be able to create a reference to S(T) for any T,
>>>
>>> struct Q
>>> {
>>>   S!* s; // Can hold any type of S.
>>> }
>>>
>>> and be able to access s.x, since it is common to all S.
>>>
>>> Can D do anything like this? It is sort of like runtime inheritance, but
>>> at the compile time level.
>>
>> I don't think so. You'd have to cast, as the compiler doesn't have any
>> understanding that all S instantiations will have an x member.
>
> This is a problem. How can I cast to something I don't know?

First, you have to store it somehow. I don't really know the way you can 
do this without a union or a Variant.

Then you can cast it to any concrete version of S, they all have an x 
member.

>>
>>> I do not want to have to cast to S!T every time just to access x, e.g.,
>>>
>>> struct Q
>>> {
>>>    Object s;
>>> }
>>>
>>> which is too general as s can be things that are not of type S!*.
>>
>> This seems odd. You will lose the type information for s if you were
>> to succeed. Might as well just store an int.
>
>> Seems like what you want is a variant or some other kind of tagged union.
>
> No, what I want is a type that is the intersection of all the types it
> can be.

Then you want std.variant.Variant. That's the only type that can change 
types at runtime.

> The problem is I cannot cast because the type is complex and I don't
> know the exact signature, but I do know that it has a basic type
> embedded in it.
>
> enum Types
> {
>    Int, Word, Complex
> }
>
> struct MyType(string name, Types type, Args...)
> {
>     string Name = name;
>     Types Type = type;
>     static if (type == Int) int val;
>     static if (type == word) ushort val;
>     static if (type == Complex) { ... };
> }
>
>
> So, how can I get val? I know if it is an int or a word, val exists. But
> I can't specify the name or type at runtime to get at the innards of the
> type.

You need to know the type. Otherwise, how will the compiler be able to 
reserve enough space for it? Variant works by having enough space to 
store most things, and then boxes if it gets bigger.

With Variant, you can type stored at runtime.

>
> Object o = MyType!("test", Types.Int);

Note that structs are not Objects. There is no base type for structs.

> Useless! I can never retrieve anything from o. I can't cast it back. Yet
> I know that o has a name and a type and possibly a val if I know the
> type... and I know all this at compile time. Yet D doesn't seem to allow
> me to use this information.
>
> I know one will say use either oop or constructors, but neither of these
> are appropriate(although constructors are close). What I need is a type
> constructor, which bridges the gap. This is how I am using the data
> above, to construct the object, but D treats it as part of the type,
> which I don't what.

In D, structs are not inheritable. You really do need polymorphism for 
this. I don't know you reason for rejecting classes, but I would 
recommend that. Or use Variant.

-Steve


More information about the Digitalmars-d-learn mailing list