www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - functions allowed to overload on const int vs int vs immutable int? +

reply timotheecour <timothee.cour2 gmail.com> writes:
this compiles, but equivalent in C++ (const int vs int) would 
give a
compile error (error: redefinition of 'fun'); what's the 
rationale for
allowing these overloads?

```
void fun(int src){ writeln2(); }
void fun(immutable int src){ writeln2(); }
void fun(const int src){ writeln2(); }

void main(){
   {int src=0; fun(src);} // matches fun(int)
   {immutable int src=0; fun(src);} // matches fun(immutable int)
   {const int src=0; fun(src);} // matches fun(const int)
}
```

The spec does mention `match with conversion to const` taking
precedence over `exact match` however this isn't precise: the
following would be more precise instead (at least according to 
snippet
above):
`match with conversion to/from const/immutable/mutable`

https://dlang.org/spec/function.html#function-overloading

Functions are overloaded based on how well the arguments to a 
function
can match up with the parameters. The function with the best 
match is
selected. The levels of matching are:

no match
match with implicit conversions
match with conversion to const
exact match

NOTE: this was one of the root causes of the bug I just fixed in 
https://github.com/msoucy/dproto/pull/131: "For sint32/sint64, 
this was related to an overload never being called because of dmd 
overload resolution rules regarding const vs mutable"

NOTE: somehow this msg didn't appear on forum after I had sent it 
via gmail 1 hour ago; this usually works, not sure why it didn't 
work this time; apologies if msg appears twice because of that 
but seems like a forum bug.
Jan 26
parent Marco Leise <Marco.Leise gmx.de> writes:
Am Fri, 26 Jan 2018 19:45:54 +0000
schrieb timotheecour <timothee.cour2 gmail.com>:

 this compiles, but equivalent in C++ (const int vs int) would 
 give a
 compile error (error: redefinition of 'fun'); what's the 
 rationale for
 allowing these overloads?
 
 ```
 void fun(int src){ writeln2(); }
 void fun(immutable int src){ writeln2(); }
 void fun(const int src){ writeln2(); }
There is also `inout` and `shared`. Granted, for basic types it makes no difference, but once references are involved you benefit from keeping the qualifier. A const or mutable string must be assumed to change after the function returns. Immutable strings on the other hand can be copied by reference. Immutable stuff is also implicitly shared, so can be used by multiple threads without synchronization. Optimizations for mutable versions only are also possible, like in-place editing. If your implementation is the same for immutable and mutable qualifiers, just provide the const version, but keep in mind that the type qualifiers are lost then. Any functions you call further down will also use their "const" implementation. Doing this as an overload of course helps with generic programming and maintenance. You can migrate from "const" only to providing multiple implementations without inventing new names or breaking code. It may also have to do with how C++'s const is not much more than a static check, while D's immutable is both transitive and supposed to give strong guarantees that the object never changes. That assumption is somewhat tied to the idea that immutable objects are either in read-only sections of the executable or that the garbage collector will keep them alive until all references are gone. -- Marco
Jan 27