Template parameters that don't affect template type

Steven Schveighoffer via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Aug 11 13:39:42 PDT 2016


On 8/11/16 4:15 PM, Engine Machine wrote:
> 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.

OK, I'll use a different example:

struct S(int N)
{
    int x;
}

S!1 s1;
S!2 s2 = s1; // error

This is very similar to what you are asking for.

This can be reimagined like so:

struct S1
{
    int x;
}

struct S2
{
    int x;
}

S1 s1;
S2 s2 = s1; // error

The names end in a different number. They have the same types and 
structure, but the compiler considers them to be different types.

Each instantiation of a template defines a DIFFERENT namespace. The only 
time the namespaces are identical are when the template parameters are 
identical. The reason templates are so useful is because I don't HAVE to 
write both S1 and S2. I can write it once and not have to repeat myself. 
But the template itself is not a namespace. Only the instantiated 
template is one.

> 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.

Not at all. This is way off.

> 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.

The namespace in which the type is declared depends on the parameter. 
Templates depend on this.

For instance:

template Foo(string name)
{
    static int x;
}

Foo!"blah".x = 5;

auto y = Foo!"blar".x;

The namespace I've declared depends on the name I've passed the 
template. I want to fetch a *different* x when I declare a *different* 
namespace. That's the point!

If the compiler said "hey, you aren't using the name string, so I'm just 
going to assume all these are the same", that's going to screw up the 
entire purpose of this construct.

> 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;

No, you have

X100 x;
X50 y;

Where X100 and X50 have the exact same structure. But they are different 
types because the names are different.

> 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.

Again, not how templates work. You are looking for a different mechanism.

-Steve


More information about the Digitalmars-d-learn mailing list