|
Archives
D Programming
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.ide
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger
D.gnu
D
C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows
digitalmars.empire
digitalmars.DMDScript
electronics
|
digitalmars.D.learn - template specialization question
According to http://digitalmars.com/d/2.0/template.html it is possible to
specify template specialization so that DMD prefers them when instanciating
templates, however the following code:
---------------------------------
import std.stdio;
void print(T)(T thing)
{
writeln("Calling print(T)");
writeln(T.stringof);
}
void print(T:T[])(T[] things)
{
writeln("Calling print(T[])");
writeln(T.stringof);
}
void main()
{
print(3);
print([1,2,3]);
}
-----------------------------------------
will output:
Calling print(T)
int
Calling print(T)
int[3u]
I expected it to output "calling print(T[])" on the second "print". Would this
be a bug or did I misunderstand the template specialization?
daoryn Wrote:
According to http://digitalmars.com/d/2.0/template.html it is possible to
specify template specialization so that DMD prefers them when instanciating
templates, however the following code:
---------------------------------
import std.stdio;
void print(T)(T thing)
{
writeln("Calling print(T)");
writeln(T.stringof);
}
void print(T:T[])(T[] things)
{
writeln("Calling print(T[])");
writeln(T.stringof);
}
void main()
{
print(3);
print([1,2,3]);
}
-----------------------------------------
will output:
Calling print(T)
int
Calling print(T)
int[3u]
I expected it to output "calling print(T[])" on the second "print". Would this
be a bug or did I misunderstand the template specialization?
It looks like the type of the array literal is a static array, not a dynamic
one.
Static arrays can be matched with the following specification:
void print(T : U[N], U, size_t N)(T things)
Or you could use the slice operator to transform the static array into a
dynamic one.
eg print([1,2,3][]);
Daniel Murphy Wrote:
daoryn Wrote:
According to http://digitalmars.com/d/2.0/template.html it is possible to
specify template specialization so that DMD prefers them when instanciating
templates, however the following code:
---------------------------------
import std.stdio;
void print(T)(T thing)
{
writeln("Calling print(T)");
writeln(T.stringof);
}
void print(T:T[])(T[] things)
{
writeln("Calling print(T[])");
writeln(T.stringof);
}
void main()
{
print(3);
print([1,2,3]);
}
-----------------------------------------
will output:
Calling print(T)
int
Calling print(T)
int[3u]
I expected it to output "calling print(T[])" on the second "print". Would this
be a bug or did I misunderstand the template specialization?
It looks like the type of the array literal is a static array, not a dynamic
one.
Static arrays can be matched with the following specification:
void print(T : U[N], U, size_t N)(T things)
Or you could use the slice operator to transform the static array into a
dynamic one.
eg print([1,2,3][]);
Sadly, your solution doesnt apply. The used template is still the wrong one.
Code:
void print(T)(T thing)
{
writeln("Calling print(T)");
writeln(T.stringof);
}
void print(T:T[])(T[] things)
{
writeln("Calling print(T[])");
writeln(T.stringof);
}
void main()
{
print(3);
print([1,2,3][]);
}
---------------
output:
Calling print(T)
int
Calling print(T)
int[]
NOTE: DMD2.040 used.
I haven't gotten around to templates yet, so I don't grok them quite as
well as I'd like, but it looks like DMD is having trouble deducing T
from the parameter given.
print([1,2,3]) fails to match the specialized template, even when the
general template is removed.
If you force the template parameter, it does what you would expect:
print!(int)(3);
print!(int[3])([1,2,3]);
Calling print(T)
int
Calling print(T[])
int
Can't say whether this belongs in bugzilla or not. It might.
On 01/31/2010 12:49 PM, daoryn wrote:
I expected it to output "calling print(T[])" on the second "print". Would this
be a bug or did I misunderstand the template specialization?
Ellery Newcomer Wrote:
I haven't gotten around to templates yet, so I don't grok them quite as
well as I'd like, but it looks like DMD is having trouble deducing T
from the parameter given.
print([1,2,3]) fails to match the specialized template, even when the
general template is removed.
If you force the template parameter, it does what you would expect:
print!(int)(3);
print!(int[3])([1,2,3]);
Calling print(T)
int
Calling print(T[])
int
Can't say whether this belongs in bugzilla or not. It might.
On 01/31/2010 12:49 PM, daoryn wrote:
I expected it to output "calling print(T[])" on the second "print". Would this
be a bug or did I misunderstand the template specialization?
The whole point of specialisation (and of templates in general) is to have
functions that work for any type. Having to forcibly specify a type is like
casting to a specific overload of a function. Why add clutter to the syntax
when the language advertises automatic type inference?
On 02/01/2010 04:19 PM, daoryn wrote:
The whole point of specialisation (and of templates in general) is to have
functions that work for any type. Having to forcibly specify a type is like
casting to a specific overload of a function. Why add clutter to the syntax
when the language advertises automatic type inference?
I disagree. The whole point of specialization is to isolate specific
cases that you want to handle differently. The point of templates
(probably not in whole) is to parameterize types. The point of argument
deduction is, as you put it, to have functions that work for any type.
I do agree that you shouldn't be having any problem whatsoever, but my
previous example illustrated that specialization is not at fault. DMD
just can't deduce what T is given the argument either because the syntax
logically doesn't make sense, or because DMD is retarded.
try compiling the following:
import std.stdio;
void print(T:T[])(T[] thing){
writeln("Calling print(T[])");
writeln(T.stringof);
}
void main()
{
print([1,2,3]);
}
it gives me:
test.d(8): Error: template test.print(T : T[]) does not match any
function template declaration
test.d(8): Error: template test.print(T : T[]) cannot deduce template
function from argument types !()(int[3u])
Dnia 31-01-2010 o 19:49:44 daoryn <manse fots.po> napisa=B3(a):
import std.stdio;
void print(T)(T thing)
{
writeln("Calling print(T)");
writeln(T.stringof);
}
void print(T:T[])(T[] things)
{
writeln("Calling print(T[])");
writeln(T.stringof);
}
void main()
{
print(3);
print([1,2,3]);
}
I'd say it should be more like:
// specialization needed to limit matching types
void print(T:int)(T thing)
{
writeln("Calling print(T)");
writeln(T.stringof);
}
// T is an array of any Us.
void print(T:U[], U)(T things)
{
writeln("Calling print(T[])");
writeln(T.stringof);
}
Tomek
Dnia 31-01-2010 o 20:59:47 Tomek Sowi=F1ski <just ask.me> napisa=B3(a):
// specialization needed to limit matching types
void print(T:int)(T thing)
To be clear -- I did this to silence the compiler saying the call with =
array matches more than one function template declaration. I'm not sure =
=
whether the compiler is right -- it has a print specifically for arrays =
so =
it should be picked over plain print(T) as it's more specialized... any =
=
template expert here?
Tomek
� wrote:
Dnia 31-01-2010 o 20:59:47 Tomek Sowi�ski <just ask.me> napisa�(a):
// specialization needed to limit matching types
void print(T:int)(T thing)
To be clear -- I did this to silence the compiler saying the call with
array matches more than one function template declaration. I'm not sure
whether the compiler is right -- it has a print specifically for arrays
so it should be picked over plain print(T) as it's more specialized...
any template expert here?
Tomek
It works with dmd 2.040 without the :int specialization.
Also, for variety, i've used the 'is' expression as described here
http://digitalmars.com/d/2.0/expression.html#IsExpression
for "conditional compilation" in the program below. I think
specialization vs. conditional compilation differ semantically this way
(no expert here! :) ):
specialization: Use this definition for T matching U[]
is expression: Consider this definition only for T matching U[]
The effect should be the same in this case; but it feels like there must
be a difference. :)
import std.stdio;
void print(T)(T thing)
{
writeln("Calling print(T)");
writeln(T.stringof);
}
// T is an array of any Us.
void print(T, U)(T things)
if (is (T == U[])) // <-- is expression
{
writeln("Calling print(T[])");
writeln(T.stringof);
}
void main()
{
print(3);
print([1,2,3]);
}
Also it could be is (T : U[]) as well, which differs from is (T == U[])
as explained at the link above.
Ali
It works with dmd 2.040 without the :int specialization.
No it doesnt. Did you use specific compiler flags? Also check that you are
using the source I posted and not the modified versions presented which served
only to circumvent compiler warnings and not answer the original question: is
it a compiler bug or misinterpreted template specialization?
Tomek Sowiński Wrote:
Dnia 31-01-2010 o 21:39:21 Ali Çehreli <acehreli yahoo.com> napisał(a):
� wrote:
Dnia 31-01-2010 o 20:59:47 Tomek Sowi�ski <just ask.me> napisa�(a):
// specialization needed to limit matching types
void print(T:int)(T thing)
array matches more than one function template declaration. I'm not sure
whether the compiler is right -- it has a print specifically for arrays
so it should be picked over plain print(T) as it's more specialized...
any template expert here?
Tomek
It works with dmd 2.040 without the :int specialization.
It's high time I upgraded, then.
Also, for variety, i've used the 'is' expression as described here
http://digitalmars.com/d/2.0/expression.html#IsExpression
for "conditional compilation" in the program below. I think
specialization vs. conditional compilation differ semantically this way
(no expert here! :) ):
specialization: Use this definition for T matching U[]
is expression: Consider this definition only for T matching U[]
The effect should be the same in this case; but it feels like there must
be a difference. :)
import std.stdio;
void print(T)(T thing)
{
writeln("Calling print(T)");
writeln(T.stringof);
}
// T is an array of any Us.
void print(T, U)(T things)
if (is (T == U[])) // <-- is expression
{
writeln("Calling print(T[])");
writeln(T.stringof);
}
void main()
{
print(3);
print([1,2,3]);
}
Also it could be is (T : U[]) as well, which differs from is (T == U[])
as explained at the link above.
Ali
Or even simpler:
void print(T)(T[] things)
But that's "regular" not template overloading.
Tomek
The "is" solution is simpler if one uses the "isArray!()" from std.traits. The
function can then be correctly implemented but the original issue remains: is
it a compiler bug or misinterpretation of the spec?
Adding an additional hidden type is just awkward when simpler solutions exist
(and are advertised on the spec). Why go into the clutter of conditional
compilation if simple template overloading should work?
Dnia 31-01-2010 o 21:39:21 Ali =C3=87ehreli <acehreli yahoo.com> napisa=C5=
=82(a):
=EF=BF=BD wrote:
Dnia 31-01-2010 o 20:59:47 Tomek Sowi=EF=BF=BDski <just ask.me> napis=
// specialization needed to limit matching types
void print(T:int)(T thing)
array matches more than one function template declaration. I'm not su=
whether the compiler is right -- it has a print specifically for arra=
so it should be picked over plain print(T) as it's more specialized..=
any template expert here?
Tomek
It works with dmd 2.040 without the :int specialization.
It's high time I upgraded, then.
Also, for variety, i've used the 'is' expression as described here
http://digitalmars.com/d/2.0/expression.html#IsExpression
for "conditional compilation" in the program below. I think =
specialization vs. conditional compilation differ semantically this wa=
(no expert here! :) ):
specialization: Use this definition for T matching U[]
is expression: Consider this definition only for T matching U[]
The effect should be the same in this case; but it feels like there mu=
be a difference. :)
import std.stdio;
void print(T)(T thing)
{
writeln("Calling print(T)");
writeln(T.stringof);
}
// T is an array of any Us.
void print(T, U)(T things)
if (is (T =3D=3D U[])) // <-- is expression
{
writeln("Calling print(T[])");
writeln(T.stringof);
}
void main()
{
print(3);
print([1,2,3]);
}
Also it could be is (T : U[]) as well, which differs from is (T =3D=3D=
as explained at the link above.
Ali
Or even simpler:
void print(T)(T[] things)
But that's "regular" not template overloading.
Tomek
daoryn wrote:
According to http://digitalmars.com/d/2.0/template.html it is
when instanciating templates, however the following code:
---------------------------------
import std.stdio;
void print(T)(T thing)
{
writeln("Calling print(T)");
writeln(T.stringof);
}
void print(T:T[])(T[] things)
Regardless of the intent of the document, which may very well be
outdated or wrong at this time; the specialization above is confusing.
If (T:T[]) is supposed to mean "array type", then the function parameter
'T[] things' above would mean "array of array". i.e. If T is T[], then
the parameter is T[][]...
For that reason this is more logical to me, and I would expect it to be
sufficient to express the specialization:
void print(T:T[])(T things)
But it still selects the general definition above...
I don't know... :)
Ali
On 02/01/2010 07:29 PM, Ali Çehreli wrote:
daoryn wrote:
> According to http://digitalmars.com/d/2.0/template.html it is
possible to specify template specialization so that DMD prefers them
when instanciating templates, however the following code:
>
>
> ---------------------------------
> import std.stdio;
>
> void print(T)(T thing)
> {
> writeln("Calling print(T)");
> writeln(T.stringof);
> }
>
> void print(T:T[])(T[] things)
Regardless of the intent of the document, which may very well be
outdated or wrong at this time; the specialization above is confusing.
It is.
If (T:T[]) is supposed to mean "array type", then the function parameter
'T[] things' above would mean "array of array". i.e. If T is T[], then
the parameter is T[][]...
I wondered that too.
I think what happens is the type is matched to T[], and not T, and then
it figures out from there what T should be, so that T[] in the function
parameter is the same as the type passed in.
For that reason this is more logical to me, and I would expect it to be
sufficient to express the specialization:
void print(T:T[])(T things)
But it still selects the general definition above...
I don't know... :)
Ali
|
|