Implicit Constructors

Q. Schroll qs.il.paperinik at gmail.com
Thu Oct 12 23:57:04 UTC 2017


We have some sort of implicit construction already. Weirdly, it's 
reserved for classes. Just look at this:

     class C { this(int x) { } }
     void foo(C c ...) { }
     void main() { foo(0); }

If you put @nogc in front of ctor and functions, the compiler 
tells you not to use 'new' in main while you actually don't. 
Merely the compiler inserts it for you to complain about it.

One could propose to extend the three-dots notation to structs. I 
don't. I'd vote for deprecating the three-dots for classes. Did 
you know it exists? Did you use it - like ever? Does anyone 
depend on it?

(If you don't want to read it all: The examples may be expressing 
enough.)

The main point of this post is a library solution to implicit 
constructor calls. The implementation is very conservative: A 
double handshake; not the constructors must be annotated with 
@implicit, the functions which want to allow being called with a 
constructor parameter must explicitly state that (these functions 
are called "receiving" functions). @implicit constructors must 
have exactly one parameter (no defaulted additional ones) and a 
receiving function has an annotation @implicit(i) where i is the 
index of a parameter for which it will be allowed to plug in a 
constructor argument of its type. Sounds complicated? See an 
example.

     struct S
     {
         import bolpat.implicitCtor : implicit;
         long s;
         @implicit this(int x)  { s = x; }
         @implicit this(long x) { s = x; }
         this(bool x) { s = x ? 0 : -1; }
     }

This is all that you need from the one side. Now the receiver 
side.

     import bolpat.implicitCtor : implicit, implicitOverloads;

     long proto_goo(int v, S s, bool b) @implicit(1)
     {
         import std.stdio : writeln;
         writeln("goo: call S with value ", s.s);
         return b ? v : s.s;
     }
     void proto_goo(char c) { } // no @implicit(i) ==> will be 
ignored

     mixin implicitOverloads!("goo", proto_goo); // generates goo

     assert(goo(1, 2, false) == 2);

It also works for members. See:

     struct Test
     {
         int proto_foo(int v, S s) @implicit(1)
         {
             import std.stdio : writeln;
             writeln("foo: call S with value ", s.s);
             return v;
         }

         void proto_foo(char c) { } // ignored

         mixin implicitOverloads!("foo", proto_foo);
     }

What to do further? Make @implicit take more than one argument. 
I'm working on it. This is just a first taste. And for Stefan 
Koch, thanks to static foreach, one can safe so many templates.

tl;dr the implementation is here:
https://github.com/Bolpat/dUtility/blob/master/bolpat/implicitCtor.d


More information about the Digitalmars-d mailing list