digitalmars.D.learn - Why doesn't this work in D2?
- Jacob Carlborg <doob me.com> Jun 27 2010
- Ellery Newcomer <ellery-newcomer utulsa.edu> Jun 27 2010
- "Simen kjaeraas" <simen.kjaras gmail.com> Jun 27 2010
- bearophile <bearophileHUGS lycos.com> Jun 27 2010
- Jacob Carlborg <doob me.com> Jun 27 2010
- BCS <none anon.com> Jun 27 2010
- Jacob Carlborg <doob me.com> Jun 28 2010
- Jacob Carlborg <doob me.com> Jun 28 2010
- BCS <none anon.com> Jun 28 2010
- Jacob Carlborg <doob me.com> Jun 28 2010
- Philippe Sigaud <philippe.sigaud gmail.com> Jun 28 2010
- "Steven Schveighoffer" <schveiguy yahoo.com> Jun 28 2010
- Philippe Sigaud <philippe.sigaud gmail.com> Jun 28 2010
Why doesn't the following code work in D2 (it works in D1)?
void foo (T) (in T[] a, T b)
{
}
void main ()
{
"asd".foo('s');
}
The error I get is:
main.d(10): Error: template main.foo(T) does not match any function
template declaration
main.d(10): Error: template main.foo(T) cannot deduce template function
from argument types !()(string,char)
It seems to be some problem with the "b" argument, if I change that to
"char" it works.
--
/Jacob Carlborg
Jun 27 2010
On 06/27/2010 12:18 PM, Jacob Carlborg wrote:Why doesn't the following code work in D2 (it works in D1)? void foo (T) (in T[] a, T b) { } void main () { "asd".foo('s'); }
"asd".foo(cast(immutable) 's');
Jun 27 2010
Jacob Carlborg <doob me.com> wrote:Why doesn't the following code work in D2 (it works in D1)? void foo (T) (in T[] a, T b) { } void main () { "asd".foo('s'); } The error I get is: main.d(10): Error: template main.foo(T) does not match any function template declaration main.d(10): Error: template main.foo(T) cannot deduce template function from argument types !()(string,char) It seems to be some problem with the "b" argument, if I change that to "char" it works.
In D2, strings are of type immutable(char)[], so your T would be immutable(char). However, 's' is a simple, unadorned char. Ways to fix this would include: void foo(T)(const T[] a, const T b){ ... } void foo(T,U)(const T[] a, U b) if (is(Unqual!T == Unqual!U)) { ... } -- Simen
Jun 27 2010
Simen kjaeraas:void foo(T,U)(const T[] a, U b) if (is(Unqual!T == Unqual!U)) { ... }
Yes, this was my solution. My first solution was: import std.traits: Unqual; void foo(T)(T[] a, Unqual!T b) {} void main () { "asd".foo('s'); } But it doesn't work, and I don't know if it's supposed to work. A problem with Unqual is that it strips away too much, so something like this can be better: void foo(TA, T)(const TA[] a, T b) if (is(Deconst!TA == Deconst!T)) {} Bye, bearophile
Jun 27 2010
On 2010-06-27 19:26, Simen kjaeraas wrote:Jacob Carlborg <doob me.com> wrote:Why doesn't the following code work in D2 (it works in D1)? void foo (T) (in T[] a, T b) { } void main () { "asd".foo('s'); } The error I get is: main.d(10): Error: template main.foo(T) does not match any function template declaration main.d(10): Error: template main.foo(T) cannot deduce template function from argument types !()(string,char) It seems to be some problem with the "b" argument, if I change that to "char" it works.
In D2, strings are of type immutable(char)[], so your T would be immutable(char). However, 's' is a simple, unadorned char. Ways to fix this would include: void foo(T)(const T[] a, const T b){ ... } void foo(T,U)(const T[] a, U b) if (is(Unqual!T == Unqual!U)) { ... }
That's annoying, specially since "char" is a value type. I would preferably have a solution for both D1 and D2. Can I use a template to cast/alias away the immutable part? -- /Jacob Carlborg
Jun 27 2010
Hello Jacob,That's annoying, specially since "char" is a value type. I would preferably have a solution for both D1 and D2. Can I use a template to cast/alias away the immutable part?
One solution would be to have templates strip off const/immutable from the top level of args. void F1(T)(T t) { pragam(msg,typeof(t).stringof); } string s1; immutable(char[]) s2 char[] s3 F1(s1); // immutable(char)[] // all as normal F1(s2); // immutable(char)[] // making a mutable copy of a immutable value is OK F1(s3); // char[] // all as normal void F2(T)(immutable T t) { pragam(msg,typeof(t).stringof); } F2(s1); // immutable(char[]) // making an immutable copy of a mutable reference to immutable data is ok F2(s2); // immutable(char[]) // all as normal F2(s3); // error, invalid conversion This solution would match the proposal that popped up a while ago to allow value assignment from const/immutable to mutable. -- ... <IXOYE><
Jun 27 2010
On 2010-06-28 02:28, BCS wrote:Hello Jacob,That's annoying, specially since "char" is a value type. I would preferably have a solution for both D1 and D2. Can I use a template to cast/alias away the immutable part?
One solution would be to have templates strip off const/immutable from the top level of args. void F1(T)(T t) { pragam(msg,typeof(t).stringof); } string s1; immutable(char[]) s2 char[] s3 F1(s1); // immutable(char)[] // all as normal F1(s2); // immutable(char)[] // making a mutable copy of a immutable value is OK F1(s3); // char[] // all as normal void F2(T)(immutable T t) { pragam(msg,typeof(t).stringof); } F2(s1); // immutable(char[]) // making an immutable copy of a mutable reference to immutable data is ok F2(s2); // immutable(char[]) // all as normal F2(s3); // error, invalid conversion This solution would match the proposal that popped up a while ago to allow value assignment from const/immutable to mutable.
I don't think I understand what you're showing here. How would I strip off the const/immutable with a template ? -- /Jacob Carlborg
Jun 28 2010
On 2010-06-28 14:14, Philippe Sigaud wrote:On Mon, Jun 28, 2010 at 10:56, Jacob Carlborg <doob me.com <mailto:doob me.com>> wrote: Something to keep in mind: as of 2.04x (.045? maybe), the way UTF-8 / UTF-32 is managed was changed. "asd" is an array of immutable(dchar), not imutable(char). At least DMD tells me that its element type is 'dchar'. So your function can be done this way in D2: void foo(T,U)(in T[] a, U b) if (is(U : Unqual!T)) // that compiles only if b can be cast to A { writeln(a,b); } "asd".foo('s'); // prints "asds". is(U == Unqual!T) does not work, for U is 'char' while Unqual!T is 'dchar'. More generally, using ranges and not arrays, the template becomes a bit more heavy: void foo(Range,Elem)(in Range range, Elem elem) if (isInputRange!Range && is(Elem : Unqual!(ElementType!Range))) { ... } I don't think I understand what you're showing here. How would I strip off the const/immutable with a template ? Hmmm... * plays with is expressions * This seems to work: template UnConst(T) { static if (is(T t == const U, U)) // that is: 'if T is a 'const U', for some U' alias U UnConst; // then give me the U, (ie, T without a const) else alias T UnConst; // else give me the (original) T } template UnImmutable(T) { static if (is(T t == immutable U, U)) // 'if T is an 'immutable U', for some U' alias U UnImmutable; else alias T UnImmutable; } test: void main() { alias const int Int; writeln(UnConst!Int.stringof); writeln(Int.stringof); writeln(UnConst!int.stringof); writeln(UnConst!(const int).stringof); writeln(UnConst!(immutable int).stringof); alias immutable int IInt; writeln(UnConst!IInt.stringof); writeln(IInt.stringof); writeln(UnImmutable!int.stringof); writeln(UnImmutable!(const int).stringof); writeln(UnImmutable!(immutable int).stringof); } Philippe
Hmm, now I don't know what I'm doing, I thought you could do something like this: template Char (T) { alias T Char; } void foo (T) (Char!(T) b) { } void main () { foo('s'); } -- /Jacob Carlborg
Jun 28 2010
Hello Jacob,On 2010-06-28 02:28, BCS wrote:One solution would be to have templates strip off const/immutable from the top level of args.
This solution would match the proposal that popped up a while ago to allow value assignment from const/immutable to mutable.
off the const/immutable with a template ?
I was proposing a language change Sorry for any confusion. The idea is that unless the user ask for it explicitly, there is no particular reason to preserve const/immutable for the value portion (true value types and the first level of references/pointers) of arguments. -- ... <IXOYE><
Jun 28 2010
On 2010-06-28 15:48, BCS wrote:Hello Jacob,On 2010-06-28 02:28, BCS wrote:One solution would be to have templates strip off const/immutable from the top level of args.
This solution would match the proposal that popped up a while ago to allow value assignment from const/immutable to mutable.
off the const/immutable with a template ?
I was proposing a language change Sorry for any confusion. The idea is that unless the user ask for it explicitly, there is no particular reason to preserve const/immutable for the value portion (true value types and the first level of references/pointers) of arguments.
Ok, now I understand. -- /Jacob Carlborg
Jun 28 2010
--0016e6dbde10001ea1048a160feb
Content-Type: text/plain; charset=ISO-8859-1
On Mon, Jun 28, 2010 at 10:56, Jacob Carlborg <doob me.com> wrote:
Something to keep in mind: as of 2.04x (.045? maybe), the way UTF-8 / UTF-32
is managed was changed. "asd" is an array of immutable(dchar), not
imutable(char). At least DMD tells me that its element type is 'dchar'.
So your function can be done this way in D2:
void foo(T,U)(in T[] a, U b) if (is(U : Unqual!T)) // that compiles only if
b can be cast to A
{
writeln(a,b);
}
"asd".foo('s'); // prints "asds".
is(U == Unqual!T) does not work, for U is 'char' while Unqual!T is 'dchar'.
More generally, using ranges and not arrays, the template becomes a bit more
heavy:
void foo(Range,Elem)(in Range range, Elem elem)
if (isInputRange!Range && is(Elem : Unqual!(ElementType!Range)))
{
...
}
I don't think I understand what you're showing here. How would I strip off
the const/immutable with a template ?
* plays with is expressions *
This seems to work:
template UnConst(T)
{
static if (is(T t == const U, U)) // that is: 'if T is a 'const U', for
some U'
alias U UnConst; // then give me the U, (ie, T
without a const)
else
alias T UnConst; // else give me the (original)
T
}
template UnImmutable(T)
{
static if (is(T t == immutable U, U)) // 'if T is an 'immutable U', for
some U'
alias U UnImmutable;
else
alias T UnImmutable;
}
test:
void main() {
alias const int Int;
writeln(UnConst!Int.stringof);
writeln(Int.stringof);
writeln(UnConst!int.stringof);
writeln(UnConst!(const int).stringof);
writeln(UnConst!(immutable int).stringof);
alias immutable int IInt;
writeln(UnConst!IInt.stringof);
writeln(IInt.stringof);
writeln(UnImmutable!int.stringof);
writeln(UnImmutable!(const int).stringof);
writeln(UnImmutable!(immutable int).stringof);
}
Philippe
--0016e6dbde10001ea1048a160feb
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div class=3D"gmail_quote">On Mon, Jun 28, 2010 at 10:56, Jacob Carlborg <s=
pan dir=3D"ltr"><<a href=3D"mailto:doob me.com">doob me.com</a>></spa=
n> wrote:<br><div><br>Something to keep in mind: as of 2.04x (.045? maybe),=
the way UTF-8 / UTF-32 is managed was changed. "asd" is an array=
of immutable(dchar), not imutable(char). At least DMD tells me that its el=
ement type is 'dchar'.<br>
<br>So your function can be done this way in D2:<br><br>void foo(T,U)(in T[=
] a, U b) if (is(U : Unqual!T)) // that compiles only if b can be cast to A=
<br>{<br>=A0=A0=A0 writeln(a,b);<br>}<br><br>"asd".foo('s'=
;); // prints "asds".<br>
<br>is(U =3D=3D Unqual!T) does not work, for U is 'char' while Unqu=
al!T is=20
'dchar'.<br><br>More generally, using ranges and not arrays, the te=
mplate becomes a bit more heavy:<br><br>void foo(Range,Elem)(in Range range=
, Elem elem) <br>if (isInputRange!Range && is(Elem : Unqual!(Elemen=
tType!Range)))<br>
{<br>...<br>}<br>=A0<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); p=
adding-left: 1ex;"><div>I don't think I understand what you're show=
ing here. How would I strip off the const/immutable with a template ?<br>
</div><br></blockquote><div><br>Hmmm...<br>* plays with is expressions *<br=
<br>This seems to work:<br><br>template UnConst(T)<br>{<br>=A0=A0=A0 stati=
', for some U'<br>
=A0=A0=A0=A0=A0=A0=A0 alias U UnConst;=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0=A0=A0 // then give me the U, (ie, T without a const)<=
br>=A0=A0=A0 else<br>=A0=A0=A0=A0=A0=A0=A0 alias T UnConst;=A0=A0=A0=A0=A0=
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 // else give me the (origi=
nal) T<br>}<br><br>template UnImmutable(T)<br>
{<br>=A0=A0=A0 static if (is(T t =3D=3D immutable U, U)) // 'if T is an=
'immutable U', for some U'<br>=A0=A0=A0=A0=A0=A0=A0 alias U Un=
Immutable;<br>=A0=A0=A0 else<br>=A0=A0=A0=A0=A0=A0=A0 alias T UnImmutable;<=
br>}<br>=A0<br>test:<br><br>void main() {<br>
=A0=A0=A0 alias const int Int;<br>=A0=A0=A0 writeln(UnConst!Int.stringof);<=
br>=A0=A0=A0 writeln(Int.stringof);<br>=A0=A0=A0 writeln(UnConst!int.string=
of);<br>=A0=A0=A0 writeln(UnConst!(const int).stringof);<br>=A0=A0=A0 write=
ln(UnConst!(immutable int).stringof);<br>
<br>=A0=A0=A0 alias immutable int IInt;<br>=A0=A0=A0 writeln(UnConst!IInt.s=
tringof);<br>=A0=A0=A0 writeln(IInt.stringof);<br>=A0=A0=A0 writeln(UnImmut=
able!int.stringof);<br>=A0=A0=A0 writeln(UnImmutable!(const int).stringof);=
<br>=A0=A0=A0 writeln(UnImmutable!(immutable int).stringof);<br>
}<br><br>Philippe<br><br></div></div>
--0016e6dbde10001ea1048a160feb--
Jun 28 2010
On Mon, 28 Jun 2010 08:14:12 -0400, Philippe Sigaud <philippe.sigaud gmail.com> wrote:On Mon, Jun 28, 2010 at 10:56, Jacob Carlborg <doob me.com> wrote: Something to keep in mind: as of 2.04x (.045? maybe), the way UTF-8 / UTF-32 is managed was changed. "asd" is an array of immutable(dchar), not imutable(char). At least DMD tells me that its element type is 'dchar'.
No, that is not true. It's still an array of immutable(char). The compiler still sees it as an array of immutable(char). However, std.range forces the element type of char[] and wchar[] to be bidirectional ranges of dchar. The tests such as isRandomAccessRange and ElementType are fudged to say string is *not* a random access range, and its element type is dchar. This was one of Andrei's changes because without such shoehorning, std.algorithm could possible start shearing off strings that weren't valid. Whether that was the right decision remains to be seen. I personally would rather have special ranges that do those things. If I have a string that's always in English, why do I need to generate the dchars based on the characters in that array? -Steve
Jun 28 2010
--0016367fb587c6b53f048a176bb2 Content-Type: text/plain; charset=ISO-8859-1 On Mon, Jun 28, 2010 at 14:35, Steven Schveighoffer <schveiguy yahoo.com>wrote:On Mon, 28 Jun 2010 08:14:12 -0400, Philippe Sigaud < philippe.sigaud gmail.com> wrote: On Mon, Jun 28, 2010 at 10:56, Jacob Carlborg <doob me.com> wrote:Something to keep in mind: as of 2.04x (.045? maybe), the way UTF-8 / UTF-32 is managed was changed. "asd" is an array of immutable(dchar), not imutable(char). At least DMD tells me that its element type is 'dchar'.
No, that is not true. It's still an array of immutable(char). The compiler still sees it as an array of immutable(char). However, std.range forces the element type of char[] and wchar[] to be bidirectional ranges of dchar. The tests such as isRandomAccessRange and ElementType are fudged to say string is *not* a random access range, and its element type is dchar. This was one of Andrei's changes because without such shoehorning, std.algorithm could possible start shearing off strings that weren't valid.
Ah yes, indeed, you're right.Whether that was the right decision remains to be seen. I personally would rather have special ranges that do those things. If I have a string that's always in English, why do I need to generate the dchars based on the characters in that array?
projects, which were using strings a simple random-access ranges. It took me 2 DMD releases to work my way uout of it. Maybe I should have a look at byCodeUnit or somesuch. But for clueless users like me, strings suddenly became much more complicated to use. Maybe I was using them in unsafe ways, I don't know. I just hope for a way to get my simple strings back. --0016367fb587c6b53f048a176bb2 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Mon, Jun 28, 2010 at 14:35, Steven Sc= hveighoffer <span dir=3D"ltr"><<a href=3D"mailto:schveiguy yahoo.com">sc= hveiguy yahoo.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote= " style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, = 204); padding-left: 1ex;"> <div class=3D"im">On Mon, 28 Jun 2010 08:14:12 -0400, Philippe Sigaud <<= a href=3D"mailto:philippe.sigaud gmail.com" target=3D"_blank">philippe.siga= ud gmail.com</a>> wrote:<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> On Mon, Jun 28, 2010 at 10:56, Jacob Carlborg <<a href=3D"mailto:doob me= .com" target=3D"_blank">doob me.com</a>> wrote:<br> <br> Something to keep in mind: as of 2.04x (.045? maybe), the way UTF-8 / UTF-3= 2<br> is managed was changed. "asd" is an array of immutable(dchar), no= t<br> imutable(char). At least DMD tells me that its element type is 'dchar&#= 39;.<br> </blockquote> <br></div> No, that is not true. =A0It's still an array of immutable(char). =A0The= compiler still sees it as an array of immutable(char). =A0However, std.ran= ge forces the element type of char[] and wchar[] to be bidirectional ranges= of dchar. =A0The tests such as isRandomAccessRange and ElementType are fud= ged to say string is *not* a random access range, and its element type is d= char. =A0This was one of Andrei's changes because without such shoehorn= ing, std.algorithm could possible start shearing off strings that weren'= ;t valid.<br> </blockquote><div><br><br>Ah yes, indeed, you're right.<br><br>=A0</div=<blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; bord=
Whether that was the right decision remains to be seen. =A0I personally wou= ld rather have special ranges that do those things. =A0If I have a string t= hat's always in English, why do I need to generate the dchars based on = the characters in that array?<br> <br></blockquote><div><br>All that I can say is that it instantly broke doz= ens of unit tests in my projects, which were using strings a simple random-= access ranges. It took me 2 DMD releases to work my way uout of it.<br> <br>Maybe I should have a look at byCodeUnit or somesuch. But for clueless = users like me, strings suddenly became much more complicated to use. Maybe = I was using them in unsafe ways, I don't know. I just hope for a way to= get my simple strings back.<br> <br><br></div></div> --0016367fb587c6b53f048a176bb2--
Jun 28 2010









Ellery Newcomer <ellery-newcomer utulsa.edu> 