Thread overview | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 11, 2016 Template parameters that don't affect template type | ||||
---|---|---|---|---|
| ||||
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. 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? 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". 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! I guess D just can't handle it though? |
August 11, 2016 Re: Template parameters that don't affect template type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Engine Machine | On Thursday, 11 August 2016 at 18:11:30 UTC, 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.
>
> 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?
>
> 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".
>
> 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!
>
> I guess D just can't handle it though?
Another good example is if something like
template X(bool ClearMemory = false)
{
}
ClearMemory would clearly not affect the type if it just clears memory that is malloc'ed, yet D would treat treat X!true from X!false.
|
August 11, 2016 Re: Template parameters that don't affect template type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Engine Machine | On Thursday, 11 August 2016 at 18:11:30 UTC, Engine Machine wrote:
> Is there any way to get D to understand I want do not want a template parameter to be part of the type comparison?
No. Use a standard run-time parameter. Your problem can be solved by defining a constructor.
|
August 11, 2016 Re: Template parameters that don't affect template type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Engine Machine | 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'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 |
August 11, 2016 Re: Template parameters that don't affect template type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Engine Machine | On 08/11/2016 11:11 AM, 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 reason they are different types is the fact that the code generated for X!100 and X!50 are different. If x=z were allowed, which foo() would you expect to be executed for x.foo()? If it would change at run time depending on the actual type, we need a run-time expression, which cannot be a template parameter. > The type it > self does not depend on the default size. > > While one could argue that it can be unsafe, in the my context, it is not. Understood but not possible with the template definition of D. > Is there any way to get D to understand I want do not want a template > parameter to be part of the type comparison? It must involve runtime. > 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". > > 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! It's not used in this module but another module may be using __traits (or std.traits) to inspect that second argument. > I guess D just can't handle it though? By design, no. (Another language that behaves this way is C++.) Ali |
August 11, 2016 Re: Template parameters that don't affect template type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 8/11/16 2:42 PM, 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?
Of course, I meant x = z :)
-Steve
|
August 11, 2016 Re: Template parameters that don't affect template type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Engine Machine | On Thursday, 11 August 2016 at 18:11:30 UTC, Engine Machine wrote:
> [...]
If, in your case, it is possible to use one type as the other, then specify it.
I mean, implement a templated opAssign that allows you to assign values of one instantiation to values of another. While doing so, remember that this will not change the behaviour of the assigned-to variable, but will only transfer the runtime state from one variable to the other.
struct S(T1, T2)
{
T1 t;
void opAssign(T)(auto ref S!(T1, T) other)
{
t = other.t;
}
}
unittest
{
S!(int, float) x(1);
S!(int, char) y(3);
x = y;
assert(x.t == 3); // the value of x is changed
static assert(is(typeof(x) == S!(int, float))) // the type of x isn't changed
}
|
August 11, 2016 Re: Template parameters that don't affect template type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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. |
August 11, 2016 Re: Template parameters that don't affect template type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lodovico Giaretta | On Thursday, 11 August 2016 at 19:28:47 UTC, Lodovico Giaretta wrote:
> On Thursday, 11 August 2016 at 18:11:30 UTC, Engine Machine wrote:
>> [...]
>
> If, in your case, it is possible to use one type as the other, then specify it.
> I mean, implement a templated opAssign that allows you to assign values of one instantiation to values of another. While doing so, remember that this will not change the behaviour of the assigned-to variable, but will only transfer the runtime state from one variable to the other.
>
> struct S(T1, T2)
> {
> T1 t;
> void opAssign(T)(auto ref S!(T1, T) other)
> {
> t = other.t;
> }
> }
> unittest
> {
> S!(int, float) x(1);
> S!(int, char) y(3);
>
> x = y;
> assert(x.t == 3); // the value of x is changed
> static assert(is(typeof(x) == S!(int, float))) // the type of x isn't changed
> }
Ok, well, my point is that in some cases, the OpAssign is trivially since everything is copied. I guess being explicit is not a bad thing in this case though.
|
August 11, 2016 Re: Template parameters that don't affect template type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Also, what if we use a class instead of a struct? in this case they are both references to the same thing. I see a problem with reflection though, as one could get the template parameter value and it would wrong on conversion. D takes the easy way out of just preventing complex and potentially ill-defined behavior, I guess that is ultimately a good thing, even if it makes it a pain in some cases. |
Copyright © 1999-2021 by the D Language Foundation