discrimination of constructors with same number of parameters

spir denis.spir at gmail.com
Thu Dec 30 05:21:43 PST 2010


On Thu, 30 Dec 2010 03:01:52 -0800
Jonathan M Davis <jmdavisProg at gmx.com> wrote:

> On Thursday 30 December 2010 02:50:55 spir wrote:
> > Hello,
> > 
> > 
> > When 2 constructors (*) accept the same number of parameters, the only
> > remaining discrimination is type. Right? But some language types (or
> > machine types) can have very diverse _human_ semantics, and thus be used
> > for various purposes which should, but cannot, be considered different:
> > this (int[] data, string filename) {...}
> > 	this (int[] data, string message) {...}
> > Aliasing like in
> > 	alias string Name;
> > does not help since for D Name is still string.
> > 
> > I know about typedef, but it is not even mentionned in TDPL, so I guess it
> > is on the deprecation path. (Am I right?) So, what is the solution for
> > this? (I added a 3rd fake bool parameter in one case)
> > 
> > Things get more complicated with unsigned integers: they can be used as
> > ordinals (index, which one), as cardinals (count, how many), as any of the
> > char types. These are completely different semantics for the "modeller"
> > (the programmer), but for the language (thus for the machine) they are the
> > same semantics.
> > 
> > Things get worse with template parameterisation, a case I lately met:
> >     Struct S (Element) {
> > 	this (int[] data, string message) {...}
> > 	this (int[] data, Element element) {...}
> > What happens when Element is string? Below an example:
> > 
> > struct S(Typ) {
> >     this(int) {writeln("int");}
> >     this(Typ) {writeln("Typ");}
> > }
> > unittest {
> >     auto s1 = S!string(1);
> >     auto s1 = S!int(1);
> > }
> > ==>
> > rdmd -w -debug -unittest -L--export-dynamic --build-only -of"__trials__"
> > "__trials__.d"
> > 
> > __trials__.d(42): Error: constructor __trials__.S!(int).S.this called with
> > argument types: ((int))
> > matches both:
> > 	__trials__.S!(int).S.this(int _param_0)
> > and:
> > 	__trials__.S!(int).S.this(int _param_0)
> > 
> > Compilation failed.
> > 
> > How do you cope with such cases?
> > 
> > Denis
> > 
> > (*) or any other func, in fact, but the issue shows up more frequently on
> > constructors, because they have good reasons to accept various parameter
> > sets.
> 
> This is a common issue in programming languages which allow for function 
> overloading. Type is what's used to determine which overload to use. If you want 
> to have two overloads that use the same types, then you're out of luck. That 
> generally means either creating another function or creating a new type (and 
> creating a new type is generally overkill). typedef is definitely on the way out, 
> so that's not a solution, and it would be a pretty fragile one IMHO anyway. So, 
> what you would do normally is create another function with another name.
> 
> In the case of constructors, you can't do that. So, if you really need it, you 
> create static factory methods which return a new value of that type. The factory 
> methods can have different names.
> 
> But function overloading works on type. So, if two overloads would crash, you 
> either have to create a new function with a new name, or you have to create a 
> new type. It may be annoying sometimes, but it's still a whale of a lot better 
> than not having function overloading at all - as is the case with languages such 
> as C and Go.

Thank you very much for this clear explanation, jonathan.

Could someone expand on the reason(s) why "typedef is definitely on the way out"? I can see pratical and conceptual advantages of having "exclusive" type defs; I mean a variant of alias for which the aliased type cannot be used where the newly type is expected.
1. Practically, this solves the above issue. For instance "typedef string Name" would discriminate two constructors.
2. Conceptually, a Name for instance is nothing like a string in general (and a message in particular). Letting the programmer use the proper is a great gain in code clarity. (See Pascal like languages for this practice.)
Additionally, this would avoid bugs where an element of a given conceptual type is used in place of another (and both happen to be the same machine type, or be compatible via casting). I have no idea how common such bugs are; but the situation is similar to frequent bugs in dynamic languages: you can pass anything to a func, thus if the operations performed there happen to accept what is passed, the bug is silently ignored.

Denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com



More information about the Digitalmars-d-learn mailing list