Determine if a type if derived from a template parameter

Alex AJ at gmail.com
Thu Apr 11 23:01:24 UTC 2019


On Thursday, 11 April 2019 at 11:45:44 UTC, Simen Kjærås wrote:
> On Thursday, 11 April 2019 at 10:49:38 UTC, Alex wrote:
>> On Thursday, 11 April 2019 at 08:57:10 UTC, Basile B. wrote:
>>> On Wednesday, 10 April 2019 at 19:28:38 UTC, Alex wrote:
>>>> e.g.,
>>>>
>>>> class X(T,S)
>>>> {
>>>>    T x;
>>>>    S y;
>>>> }
>>>>
>>>> Somehow determine if x's type is derived from the template 
>>>> parameter.
>>>>
>>>> I doubt D has this capability but it would be nice for 
>>>> certain things. In my reflect library the types must be 
>>>> specified such as Reflect!(X!(int,float)) and ideally I 
>>>> would like to do Reflect!(X!(T,S)) to get generic reflection 
>>>> information. This helps reduce overhead as one could reflect 
>>>> once on the generic type, cache the results, then simply 
>>>> modify the results for specifics.
>>>
>>> You can detect a match between a member and a template 
>>> argument but you cant know if the match is a coincidence or 
>>> on purpose. For example:
>>>
>>>   class X(T)
>>>   {
>>>       T x;
>>>       int y;
>>>   }
>>>
>>>   alias X1 = X!int;
>>>
>>> here X1.y matches to T but it's a coincidence.
>>> The problem that you'll be faced to is that the template 
>>> parameters are replaced by the symbol or the type.
>>
>> Yes, which is my point, so one isn't detecting anything. It 
>> would be very error prone to assume if a type is the same as 
>> the type of the parameter then it is that parameter.
>>
>> This is why I asked if there was a way to do this. The 
>> compiler easily knows this information since it has to do the 
>> replacement. The only way to hack it is to read the source 
>> unless there is some way way in D.
>
> There is no way to check this in D today. It's also impossible 
> in the general case, since the relationship between a field and 
> a template parameter can be arbitrarily complex:
>
> template RandomType(T) {
>     static if (__DATE__[0] == 'A')
>         alias RandomType = int;
>     else
>         alias RandomType = T;
> }
>
> struct S(T) {
>     RandomType!T a;
> }
>
> // Should print "T" unless __DATE__ starts with an A.
> // Or should it really?
> pragma(msg, __traits(getTemplateParameterName, S!string.a));
>
> For this very same reason, it's also impossible to get a 
> generic S where you can simply replace T with the type you want 
> to.
>
> Simply put, D's templates are much more powerful than the 
> generics found in Java and C#, and this power comes with some 
> cost.
>
> --
>   Simen

That is not true. Your example proves nothing. RandomType MUST at 
some point be some type.

In your case if I queried the parameter name for A, it would 
return "" when __DATE__ starts with an A, else it would return 
RandomType. RandomType could then be queried.

The compiler MUST now what the parameter name is. It also is very 
easy to get this from the source code. If it were impossible it 
would be impossible for static typing.

No matter how complex the obfuscation would be, there must be a 
deterministic path from the template parameter name to the 
instantiation of a type with it. If it were not the case how 
could the compiler possibly figure anything out?

The only question is if the compiler tracks this information so 
it can be reversed.

See, no matter how complex you want to create an example, 
Anything that depends on T to generate a type X used for 
something, there will be a path from T to X of symbols and the 
compiler knows exactly what that path is. There ultimately can 
only be a unique path and so it is reversible.

So, you are simply wrong. Trying to overcomplicated it by making 
it "random" does nothing bot obscure what is really going on. 
There is nothing random about your code(and nothing random about 
CT code, it can't be random or it couldn't be compiled).

Your code simplifies to only two possibilities:

struct S(T) {
      T a;
}

or

struct S(T) {
      int a;
}

and it only depends on what the date is, but no matter what the 
date is, either a is going to have T or it isn't, and it's only 
one case depending on the day.

So
__traits(getTemplateParameterOfMember, S!int.a) == (__DATE__[0] 
== 'A') ? "" : "T";

and there is nothing non-deterministic about that.


[I'm always amazed when someone claims something is impossible... 
it's nearly impossible to prove anything is impossible. Usually 
when people make such claims they inevitably are wrong yet many 
do without any real proof. Maybe it is a flaw in human evolution?]







More information about the Digitalmars-d mailing list