Thread overview
string, char[], overloaded functions.
Oct 31, 2014
dajones
Nov 01, 2014
Adam D. Ruppe
Nov 01, 2014
ketmar
Nov 01, 2014
Marc Schütz
Nov 01, 2014
ketmar
Nov 03, 2014
dajones
Nov 01, 2014
Jonathan M Davis
Nov 03, 2014
dajones
Nov 01, 2014
Kagamin
Nov 03, 2014
dajones
October 31, 2014
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?


November 01, 2014
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.
November 01, 2014
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

November 01, 2014
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. ;-)


November 01, 2014
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
November 01, 2014
On Sat, 01 Nov 2014 08:36:40 +0000
via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:

> No, it's `~=` that may or may not allocate, but `~` always does.
you a right. sorry, i was wrong here.


November 01, 2014
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")
November 03, 2014
"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



November 03, 2014
"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


November 03, 2014
"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