Template parameters that don't affect template type

Engine Machine via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Aug 11 13:15:41 PDT 2016


On Thursday, 11 August 2016 at 18:42:51 UTC, Steven Schveighoffer 
wrote:
> On 8/11/16 2:11 PM, Engine Machine wrote:
>> I have the need, in some cases, to pass static information to 
>> a template
>> class but don't want it to affect its type.
>>
>> import std.algorithm, core.stdc.stdlib;
>> struct X(int defaultSize = 100)
>> {
>>    int Size;
>>    int* p;
>>    void foo(int size)
>>    {
>>     Size = max(size, defaultSize);
>>     p = cast(int*)malloc(Size);
>>    }
>> }
>>
>> If I do
>>
>> X!100 x;
>> X!100 y;
>> X!50 z;
>>
>> then I can do
>>
>> x = y;
>>
>> but not
>>
>> x = z;
>>
>> but of course D things these are completely different types. 
>> The type it
>> self does not depend on the default size.
>
> And they should be different types. The code generated for the 
> type is different, in this case it's important to declare these 
> are not the same type.
>
> For example, if x = y worked, then what should x.foo(5) do?
>
>> While one could argue that it can be unsafe, in the my 
>> context, it is not.
>>
>> Is there any way to get D to understand I want do not want a 
>> template
>> parameter to be part of the type comparison?
>
> The type is part of the template, and the instantiations are 
> different. So no.
>
>> I use several parameters to pass info to the type that does 
>> not change
>> affect the type itself. It prevents the "same type" from being 
>> used with
>> "itself".
>
> Then define how the compiler can convert from one to another. 
> Or redesign the type to specify the parameters at the right 
> time.
>
>> another example:
>>
>> struct s(T1, T2)
>> {
>>     T1;
>> }
>>
>> then
>>
>> s!(int, double)
>>
>> and
>>
>> s!(int, float)
>>
>> should really be the same type! The fact that T2 is not used 
>> is important!
>
> That's not how template types work.
>
> your code is shorthand for:
>
> template s(T1, T2)
> {
>    struct s
>    {
>       T1 t1; // I assume you wanted to put a member here?
>    }
> }
>
> Two different instantiations of s create two different 
> namespaces where the structs are not the same.
>

I don't think this proves anything. You just rewrote the 
template. T2 is still not used in either case and hence the type 
does not depend on it.

Basically your logic is something like: A = 0*5 is different than 
B = 0*6. But both are the same, just because they look different 
doesn't change that.

> I'd suggest if you don't use a template parameter, don't 
> declare it. If you use it in a member function only (as in your 
> first example), declare it in the member function as a template 
> parameter.
>
>> I guess D just can't handle it though?
>
> No, it doesn't handle incorrect assumptions very well ;)
>
> -Steve

You are misunderstanding what I am asking or saying.

The code may be different, but one reference can store the value 
of another. The type itself does not depend on the parameter.

X!100 x;
X!50 y;

50 for y does not change anything to the outside world about y.

So, for all practical purposes, we have

X x;
X y;

in which case we can do

x = y; with no problem.

You are confusing the general case with the specific case. Sure, 
in general, it doesn't work, we know that. But not all types are 
dependent on their type parameter. Just because such parameters 
are specified does not necessarily mean they should be different 
types.


My example is not good because the types are different. If I did 
something like

void foo(int size)
    {
    Size = max(size, defaultSize, 100);
     p = cast(int*)malloc(Size);
    }


Then it would be different.

in this case X!50 and X!100 would be the same. X!101 would not.



More information about the Digitalmars-d-learn mailing list