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