www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - string, char[], overloaded functions.

reply "dajones" <dajones hotmail.com> writes:
Ok,

void Foo(string name, string value);
void Foo(string name, int value);

then...

char[] buf = "woo".dup;
Foo("bar","woohoo"); // works ok
Foo("bar",buf~"hoo"); // fails, error says cant match params (string, int)

So shouldnt char[] implicity convert to string, and hence match the 
(string,string) parameter list?

is there a better way than doing...

cast(string)(buf~"hoo")

to get it to pick the correct overload?
Oct 31 2014
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 31 October 2014 at 23:59:54 UTC, dajones wrote:
 So shouldnt char[] implicity convert to string
Nope, char[] casting to string is generally a bad thing that should be avoided because it can leave you with a mutable string, which isn't supposed to happen. In your case, why are you using char[] for the buf instead of just string? BTW one could argue that char[] ~ operator should yield something that's implicitly convertable, since it allocates a new memory block anyway, but that's not how it works right now.
Oct 31 2014
next sibling parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sat, 01 Nov 2014 00:05:19 +0000
"Adam D. Ruppe via Digitalmars-d-learn"
<digitalmars-d-learn puremagic.com> wrote:

 BTW one could argue that char[] ~ operator should yield something=20
 that's implicitly convertable, since it allocates a new memory=20
 block anyway, but that's not how it works right now.
it's not necessarily allocates. but `(buf~"hoo").idup` does, so it can be used. ;-)
Oct 31 2014
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Saturday, 1 November 2014 at 03:28:36 UTC, ketmar via 
Digitalmars-d-learn wrote:
 On Sat, 01 Nov 2014 00:05:19 +0000
 "Adam D. Ruppe via Digitalmars-d-learn"
 <digitalmars-d-learn puremagic.com> wrote:

 BTW one could argue that char[] ~ operator should yield 
 something that's implicitly convertable, since it allocates a 
 new memory block anyway, but that's not how it works right now.
it's not necessarily allocates. but `(buf~"hoo").idup` does, so it can be used. ;-)
No, it's `~=` that may or may not allocate, but `~` always does. I think it's an instance of this bug [1]; `buf~"hoo"` should be inferred as unique, and therefore convert to `immutable`. https://issues.dlang.org/show_bug.cgi?id=1654
Nov 01 2014
parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Sat, 01 Nov 2014 08:36:40 +0000
via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:

 No, it's `~=3D` that may or may not allocate, but `~` always does.=20
you a right. sorry, i was wrong here.
Nov 01 2014
prev sibling parent "dajones" <dajones hotmail.com> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:xxnfghisussknbqzvopt forum.dlang.org...
 On Friday, 31 October 2014 at 23:59:54 UTC, dajones wrote:
 So shouldnt char[] implicity convert to string
Nope, char[] casting to string is generally a bad thing that should be avoided because it can leave you with a mutable string, which isn't supposed to happen. In your case, why are you using char[] for the buf instead of just string?
I was using stdin.readln to read input from the console, and that takes a char[] buffer. At least the example code on dlang.org reads into a char[] buffer. I want to coble together that char[] input with some string literals. I was writing a key to the registry like this... key.setValue("keyname", buf~"Foo"); but it kept saying it couldnt match setValue(string, int), which is one f the other overloads. Thanks, Chris
Nov 02 2014
prev sibling next sibling parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Friday, October 31, 2014 23:58:43 dajones via Digitalmars-d-learn wrote:
 Ok,

 void Foo(string name, string value);
 void Foo(string name, int value);

 then...

 char[] buf = "woo".dup;
 Foo("bar","woohoo"); // works ok
 Foo("bar",buf~"hoo"); // fails, error says cant match params (string, int)

 So shouldnt char[] implicity convert to string, and hence match the
 (string,string) parameter list?

 is there a better way than doing...

 cast(string)(buf~"hoo")

 to get it to pick the correct overload?
How could char[] implicitly convert to string? string is immutable(char)[], so its elements can't be changed, whereas char[]'s can be. So, if char[] implicitly converted to immutable(char)[], either it would be by casting and make it possible to violate the immutability of the characters (because something could change the original char[] array, and then affect the supposedly immutable characters in the one that came from the cast), or it would be doing idup for you, which would then be an invisible allocation and potential performance hit. string and char[] will implicitly convert to const(char)[], but mutable types don't generally implicitly convert to immutable ones, immutable ones don't implicitly convert to mutable ones, and const doesn't implicitly convert to either. The reason that "woohoo" works is because string literals are strings, not char[]. In the case of, buf ~ "hoo", it generates a new char[] with the elements of buf and "hoo", because buf was char[], not string, and char[] isn't implicitly convertible to either string or int. If you want a function to take any type of mutability for strings, then you can use const: void foo(const(char)[] name const(char)[] value); though that has the downside of making it so that you're stuff using const, which is particularly annoying if the function returns const(char)[] foo(const(char)[] name const(char)[] value); To fix that, you can use inout inout(char)[] foo(inout(char)[] name inout(char)[] value); so that the constness stays the same, but then the constness would have to match in this case, because there are two inout parameters. If you want to accept any constness without dealing with inout and without having to use const, then you can just templatize the function, e.g. C[] foo(C, D)(C[] name, D[] value) if(is(C == char) && is(D == char)) and to accept any character type, you could do something like C[] foo(C, D)(C[] name, D[] value) if(isSomeChar!C && isSomeChar!D) but obviously that gets more complicated. In any case, the only type of argument that will be accepted for a string parameter is string, not char[] or const(char)[], and casting to string from char[] will violate the type system if any other references to that same array exist (making it possible for the supposedly immutable chars to be mutated). So, you should use either idup or to!string() (the advantage of std.conv.to being that if the argument ever changed to string, no copy would be made, whereas idup would still make a copy). - Jonathan M Davis
Oct 31 2014
parent "dajones" <dajones hotmail.com> writes:
"Jonathan M Davis via Digitalmars-d-learn" 
<digitalmars-d-learn puremagic.com> wrote in message 
news:mailman.1363.1414801299.9932.digitalmars-d-learn puremagic.com...
 On Friday, October 31, 2014 23:58:43 dajones via Digitalmars-d-learn 
 wrote:
 Ok,

 void Foo(string name, string value);
 void Foo(string name, int value);

 then...

 char[] buf = "woo".dup;
 Foo("bar","woohoo"); // works ok
 Foo("bar",buf~"hoo"); // fails, error says cant match params (string, 
 int)

 So shouldnt char[] implicity convert to string, and hence match the
 (string,string) parameter list?

 is there a better way than doing...

 cast(string)(buf~"hoo")

 to get it to pick the correct overload?
How could char[] implicitly convert to string? string is immutable(char)[], so its elements can't be changed, whereas char[]'s can be. So, if char[] implicitly converted to immutable(char)[], either it would be by casting and make it possible to violate the immutability of the characters (because something could change the original char[] array, and then affect the supposedly immutable characters in the one that came from the cast), or it would be doing idup for you, which would then be an invisible allocation and potential performance hit. string and char[] will implicitly convert to const(char)[], but mutable types don't generally implicitly convert to immutable ones, immutable ones don't implicitly convert to mutable ones, and const doesn't implicitly convert to either. The reason that "woohoo" works is because string literals are strings, not char[]. In the case of, buf ~ "hoo", it generates a new char[] with the elements of buf and "hoo", because buf was char[], not string, and char[] isn't implicitly convertible to either string or int. If you want a function to take any type of mutability for strings, then you can use const: void foo(const(char)[] name const(char)[] value); though that has the downside of making it so that you're stuff using const, which is particularly annoying if the function returns const(char)[] foo(const(char)[] name const(char)[] value); To fix that, you can use inout inout(char)[] foo(inout(char)[] name inout(char)[] value); so that the constness stays the same, but then the constness would have to match in this case, because there are two inout parameters. If you want to accept any constness without dealing with inout and without having to use const, then you can just templatize the function, e.g. C[] foo(C, D)(C[] name, D[] value) if(is(C == char) && is(D == char)) and to accept any character type, you could do something like C[] foo(C, D)(C[] name, D[] value) if(isSomeChar!C && isSomeChar!D) but obviously that gets more complicated. In any case, the only type of argument that will be accepted for a string parameter is string, not char[] or const(char)[], and casting to string from char[] will violate the type system if any other references to that same array exist (making it possible for the supposedly immutable chars to be mutated). So, you should use either idup or to!string() (the advantage of std.conv.to being that if the argument ever changed to string, no copy would be made, whereas idup would still make a copy).
My eyes were reading "immutable" but my brain was thinking "C++ const". Makes more sense now! Thanks, Chris
Nov 02 2014
prev sibling parent reply "Kagamin" <spam here.lot> writes:
On Friday, 31 October 2014 at 23:59:54 UTC, dajones wrote:
 is there a better way than doing...

 cast(string)(buf~"hoo")

 to get it to pick the correct overload?
text(buf,"hoo")
Nov 01 2014
parent "dajones" <dajones hotmail.com> writes:
"Kagamin" <spam here.lot> wrote in message 
news:lccftxangprboitrtvmh forum.dlang.org...
 On Friday, 31 October 2014 at 23:59:54 UTC, dajones wrote:
 is there a better way than doing...

 cast(string)(buf~"hoo")

 to get it to pick the correct overload?
text(buf,"hoo")
Thanks! chris
Nov 02 2014