Thread overview | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
May 20, 2015 Template type deduction and specialization | ||||
---|---|---|---|---|
| ||||
I don't understand why this behaves as it does. Given the following two templates: ``` void printVal(T)(T t) { writeln(t); } void printVal(T : T*)(T* t) { writeln(*t); } ``` I find that I actually have to explicitly instantiate the template with a pointer type to get the specialization. ``` void main() { int x = 100; printVal(x); int* px = &x; printVal(px); // prints the address printVal!(int*)(px) // prints 100 } ``` Intuitively, I would expect the specialization to be deduced without explicit instantiation. Assuming this isn't a bug (I've been unable to turn up anything in Bugzilla), could someone in the know explain the rationale behind this? |
May 20, 2015 Re: Template type deduction and specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Wednesday, 20 May 2015 at 06:31:13 UTC, Mike Parker wrote:
> I don't understand why this behaves as it does. Given the following two templates:
>
> ```
> void printVal(T)(T t) {
> writeln(t);
> }
> void printVal(T : T*)(T* t) {
> writeln(*t);
> }
> ```
>
> I find that I actually have to explicitly instantiate the template with a pointer type to get the specialization.
>
> ```
> void main() {
> int x = 100;
> printVal(x);
> int* px = &x;
> printVal(px); // prints the address
> printVal!(int*)(px) // prints 100
> }
> ```
>
> Intuitively, I would expect the specialization to be deduced without explicit instantiation. Assuming this isn't a bug (I've been unable to turn up anything in Bugzilla), could someone in the know explain the rationale behind this?
---
import std.stdio;
void printVal(T)(T t) {
writeln(t);
}
void printVal(T: T)(T* t) {
writeln(*t);
}
void main() {
int x = 100;
printVal(x);
int* px = &x;
printVal(px);
}
---
here it's selected correctly without explicit instantiation. But honestly i don't know why since the asterisk is removed from the T it looks quite incorrect.
|
May 20, 2015 Re: Template type deduction and specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Wednesday, 20 May 2015 at 06:31:13 UTC, Mike Parker wrote:
> I don't understand why this behaves as it does. Given the following two templates:
>
> ```
> void printVal(T)(T t) {
> writeln(t);
> }
> void printVal(T : T*)(T* t) {
> writeln(*t);
> }
> ```
>
> I find that I actually have to explicitly instantiate the template with a pointer type to get the specialization.
>
> ```
> void main() {
> int x = 100;
> printVal(x);
> int* px = &x;
> printVal(px); // prints the address
> printVal!(int*)(px) // prints 100
> }
> ```
>
> Intuitively, I would expect the specialization to be deduced without explicit instantiation. Assuming this isn't a bug (I've been unable to turn up anything in Bugzilla), could someone in the know explain the rationale behind this?
What about:
----
import std.stdio;
void printVal(T)(T t) {
static if (is(T : U*, U))
printVal(*t);
else
writeln(t);
}
void main() {
int x = 100;
printVal(x);
int* px = &x;
printVal(px);
}
----
|
May 20, 2015 Re: Template type deduction and specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | On 5/20/2015 4:36 PM, Namespace wrote:
> What about:
> ----
> import std.stdio;
>
> void printVal(T)(T t) {
> static if (is(T : U*, U))
> printVal(*t);
> else
> writeln(t);
> }
Thanks, but I'm not looking for alternatives. I'm trying to figure out why it doesn't work as expected.
|
May 20, 2015 Re: Template type deduction and specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Wed, 20 May 2015 06:31:11 +0000 Mike Parker via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote: > I don't understand why this behaves as it does. Given the following two templates: > > ``` > void printVal(T)(T t) { > writeln(t); > } > void printVal(T : T*)(T* t) { > writeln(*t); > } > ``` > > I find that I actually have to explicitly instantiate the template with a pointer type to get the specialization. > > ``` > void main() { > int x = 100; > printVal(x); > int* px = &x; > printVal(px); // prints the address > printVal!(int*)(px) // prints 100 > } > ``` > > Intuitively, I would expect the specialization to be deduced without explicit instantiation. Assuming this isn't a bug (I've been unable to turn up anything in Bugzilla), could someone in the know explain the rationale behind this? Because it cannot deduce type T: try this: void printVal(T : T*)(T* t) { writeln(*t); } void main() { int x = 100; int* px = &x; printVal(px); } It will print error. My advise is not to use T:T* or T:T[] it works only when explicitly instantiate. Is better use T:M*,M or T:M[], M because it works automaticly and you have both types available. import std.stdio; void printVal(T)(T t) { writeln(t); } void printVal(T:M*,M)(T t) { writeln(*t); } void main() { int x = 100; printVal(x); int* px = &x; printVal(px); // prints the 100 } |
May 20, 2015 Re: Template type deduction and specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Kozák | On Wednesday, 20 May 2015 at 09:24:28 UTC, Daniel Kozák wrote: > > On Wed, 20 May 2015 06:31:11 +0000 > Mike Parker via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> > wrote: > >> I don't understand why this behaves as it does. Given the following two templates: >> >> ``` >> void printVal(T)(T t) { >> writeln(t); >> } >> void printVal(T : T*)(T* t) { >> writeln(*t); >> } >> ``` >> >> I find that I actually have to explicitly instantiate the template with a pointer type to get the specialization. >> >> ``` >> void main() { >> int x = 100; >> printVal(x); >> int* px = &x; >> printVal(px); // prints the address >> printVal!(int*)(px) // prints 100 >> } >> ``` >> >> Intuitively, I would expect the specialization to be deduced without explicit instantiation. Assuming this isn't a bug (I've been unable to turn up anything in Bugzilla), could someone in the know explain the rationale behind this? > > Because it cannot deduce type T: > > try this: > > void printVal(T : T*)(T* t) { > writeln(*t); > } > > void main() { > int x = 100; > int* px = &x; > printVal(px); > } > > It will print error. > > My advise is not to use T:T* or T:T[] it works only when explicitly > instantiate. Is better use T:M*,M or T:M[], M because it works > automaticly and you have both types available. > > import std.stdio; > > void printVal(T)(T t) { > writeln(t); > } > > void printVal(T:M*,M)(T t) { > writeln(*t); > } > > void main() { > int x = 100; > printVal(x); > int* px = &x; > printVal(px); // prints the 100 > } DOCS: http://dlang.org/template.html#function-templates says: Function template type parameters that are to be implicitly deduced may not have specializations: |
May 20, 2015 Re: Template type deduction and specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Wednesday, May 20, 2015 06:31:11 Mike Parker via Digitalmars-d-learn wrote:
> I don't understand why this behaves as it does. Given the following two templates:
>
> ```
> void printVal(T)(T t) {
> writeln(t);
> }
> void printVal(T : T*)(T* t) {
> writeln(*t);
> }
> ```
>
> I find that I actually have to explicitly instantiate the template with a pointer type to get the specialization.
>
> ```
> void main() {
> int x = 100;
> printVal(x);
> int* px = &x;
> printVal(px); // prints the address
> printVal!(int*)(px) // prints 100
> }
> ```
>
> Intuitively, I would expect the specialization to be deduced without explicit instantiation. Assuming this isn't a bug (I've been unable to turn up anything in Bugzilla), could someone in the know explain the rationale behind this?
Well, if
printVal!(int*)(px);
prints 100, then that's a bug. It should print the address. In fact, it should be _impossible_ for the second overload of printVal to ever be instantiated. Think about it. What does T : T* mean? It means that T is implicitly convertible to T*. And when is a type ever implicitly convertible to a pointer to itself?
int x = 100;
int y = &x;
isn't going to compile, so neither should that second overload ever end up being used. Use std.traits.isPointer if you want to test for whether a type is a pointer or not.
I'm using a fairly recent version of dmd master, and it prints out the address for px in both cases when I compile your code. So, if it's printing out 100 for you on the second call, it would appear to be a bug that has been fixed at some point since 2.067 (or whatever version you're using) was released.
- Jonathan M Davis
|
May 20, 2015 Re: Template type deduction and specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | On Wednesday, May 20, 2015 07:36:21 Namespace via Digitalmars-d-learn wrote:
> What about:
> ----
> import std.stdio;
>
> void printVal(T)(T t) {
> static if (is(T : U*, U))
> printVal(*t);
> else
> writeln(t);
> }
>
> void main() {
> int x = 100;
> printVal(x);
> int* px = &x;
> printVal(px);
> }
> ----
That mostly works, but you it runs the classic risk of running into problems with alias this (which is why checking for implicit conversions in static if or template constraints is so incredibly dangerous if you're not _very_ careful). std.traits defines isPointer as follows:
enum bool isPointer(T) = is(T == U*, U) && !isAggregateType!T;
which avoids the alias this problem. Regardless, it's more idiomatic to just use isPointer.
- Jonathan M Davis
|
May 20, 2015 Re: Template type deduction and specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to jklp | On Wednesday, 20 May 2015 at 07:27:53 UTC, jklp wrote:
>
> ---
> import std.stdio;
>
> void printVal(T)(T t) {
> writeln(t);
> }
>
> void printVal(T: T)(T* t) {
> writeln(*t);
> }
>
> void main() {
> int x = 100;
> printVal(x);
> int* px = &x;
> printVal(px);
> }
> ---
>
> here it's selected correctly without explicit instantiation. But honestly i don't know why since the asterisk is removed from the T it looks quite incorrect.
No it is correct it is same as:
void printVal(T: int)(T* t) {
writeln(*t);
}
|
May 20, 2015 Re: Template type deduction and specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Wednesday, 20 May 2015 at 09:35:48 UTC, Jonathan M Davis wrote:
>
> Well, if
>
> printVal!(int*)(px);
>
> prints 100, then that's a bug. It should print the address. In fact, it
> should be _impossible_ for the second overload of printVal to ever be
> instantiated
IMHO thats not true, it should print 100. This is what spec say.
void printVal(T : T*)(T* t) {
writeln(*t);
}
T is deduce to be int so we have
void printVal(int* t) {
writeln(*t);
}
which will print value not address
|
Copyright © 1999-2021 by the D Language Foundation