www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - string literal string and immutable(char)* overload ambiguity

reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
is there any particular reason why

void foo(string a) {}
void foo(immutable(char)* b) {}

void bar()
{
     foo("baz");
}

result in

Error: foo called with argument types (string) matches both:
foo(string a)
and:
foo(immutable(char)* b)

especially given the pointer overload is almost always
void foo(immutable(char)* b)
{
     foo(b[0 .. strlen(b)]);
}
and if I really want to call the pointer variant I can with
     foo("baz".ptr);
but I can't call the string overload with a literal without 
creating a temp.

I think we should make string literals prefer string arguments.
Jul 31 2018
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/31/18 10:13 AM, Nicholas Wilson wrote:
 is there any particular reason why
 
 void foo(string a) {}
 void foo(immutable(char)* b) {}
 
 void bar()
 {
      foo("baz");
 }
 
 result in
 
 Error: foo called with argument types (string) matches both:
 foo(string a)
 and:
 foo(immutable(char)* b)
 
 especially given the pointer overload is almost always
 void foo(immutable(char)* b)
 {
      foo(b[0 .. strlen(b)]);
 }
 and if I really want to call the pointer variant I can with
      foo("baz".ptr);
 but I can't call the string overload with a literal without creating a 
 temp.
 
 I think we should make string literals prefer string arguments.
 
Absolutely, I didn't realize this was an ambiguity. It should be the same as foo(long) vs. foo(int) with foo(1). -Steve
Jul 31 2018
parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Tuesday, 31 July 2018 at 15:07:04 UTC, Steven Schveighoffer 
wrote:
 On 7/31/18 10:13 AM, Nicholas Wilson wrote:
 is there any particular reason why
 
 void foo(string a) {}
 void foo(immutable(char)* b) {}
 
 void bar()
 {
      foo("baz");
 }
 
 result in
 
 Error: foo called with argument types (string) matches both:
 foo(string a)
 and:
 foo(immutable(char)* b)
 
 especially given the pointer overload is almost always
 void foo(immutable(char)* b)
 {
      foo(b[0 .. strlen(b)]);
 }
 and if I really want to call the pointer variant I can with
      foo("baz".ptr);
 but I can't call the string overload with a literal without 
 creating a temp.
 
 I think we should make string literals prefer string arguments.
 
Absolutely, I didn't realize this was an ambiguity. It should be the same as foo(long) vs. foo(int) with foo(1). -Steve
+1 for this Although there is a solution for this today, i.e. foo(cast(string)"baz"); foo("baz".ptr)); I see no reason why `string` shouldn't have precedence over `immutable(char)*`, especially since you can always explicitly choose the pointer variant with `.ptr.
Aug 03 2018
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 8/3/18 10:26 AM, Jonathan Marler wrote:
 On Tuesday, 31 July 2018 at 15:07:04 UTC, Steven Schveighoffer wrote:
 On 7/31/18 10:13 AM, Nicholas Wilson wrote:
 is there any particular reason why

 void foo(string a) {}
 void foo(immutable(char)* b) {}

 void bar()
 {
      foo("baz");
 }

 result in

 Error: foo called with argument types (string) matches both:
 foo(string a)
 and:
 foo(immutable(char)* b)

 especially given the pointer overload is almost always
 void foo(immutable(char)* b)
 {
      foo(b[0 .. strlen(b)]);
 }
 and if I really want to call the pointer variant I can with
      foo("baz".ptr);
 but I can't call the string overload with a literal without creating 
 a temp.

 I think we should make string literals prefer string arguments.
Absolutely, I didn't realize this was an ambiguity. It should be the same as foo(long) vs. foo(int) with foo(1).
+1 for this Although there is a solution for this today, i.e. foo(cast(string)"baz"); foo("baz".ptr)); I see no reason why `string` shouldn't have precedence over `immutable(char)*`, especially since you can always explicitly choose the pointer variant with `.ptr.
Let me rewrite your solution for int vs. long: foo(cast(int)1); foo(1L); You like that too? ;) "baz" is a string, that's its primary type. That it can be used for a const(char)* is nice for legacy C code, but shouldn't get in the way of its natural type. -Steve
Aug 04 2018
parent Jonathan Marler <johnnymarler gmail.com> writes:
On Saturday, 4 August 2018 at 12:16:00 UTC, Steven Schveighoffer 
wrote:
 On 8/3/18 10:26 AM, Jonathan Marler wrote:
 On Tuesday, 31 July 2018 at 15:07:04 UTC, Steven Schveighoffer 
 wrote:
 On 7/31/18 10:13 AM, Nicholas Wilson wrote:
[...]
Absolutely, I didn't realize this was an ambiguity. It should be the same as foo(long) vs. foo(int) with foo(1).
+1 for this Although there is a solution for this today, i.e. foo(cast(string)"baz"); foo("baz".ptr)); I see no reason why `string` shouldn't have precedence over `immutable(char)*`, especially since you can always explicitly choose the pointer variant with `.ptr.
Let me rewrite your solution for int vs. long: foo(cast(int)1); foo(1L); You like that too? ;) "baz" is a string, that's its primary type. That it can be used for a const(char)* is nice for legacy C code, but shouldn't get in the way of its natural type. -Steve
Yeah I definitely agree. Though there is a solution, it's ugly. Making string have precedence over char pointers seems like only positives from what I can tell.
Aug 04 2018