Define "createXXX" functions for the constructors of class XXX

Chris Wright via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Jan 23 12:54:50 PST 2016


On Sat, 23 Jan 2016 19:42:29 +0000, Johan Engelen wrote:
> // Somehow define these guys automatically, "genCreateCtors!(XXX)" ?
>    XXX createXXX(int a, int b) { return new XXX(a, b); }
>    XXX createXXX(bool flag) { return new XXX(flag); }

Check out http://dpaste.dzfl.pl/430dabf25935

I used string mixins to be absolutely, 100% sure that the right things 
ended up in the symbol table.

__traits(getOverloads, Type, "name") gets function overloads for the 
given name. It gets them as an AliasSeq, which presents an array-like 
interface.

Constructors use the name "__ctor". So you can get all constructors for a 
class named MyClass with:

__traits(getOverloads, MyClass, "__ctor")

This only includes explicitly defined constructors, not the default 
constructor, so we handle that separately.

std.traits defines a Parameters template that takes a function and yields 
a parameter type tuple. We can hand it a constructor and it does the 
right thing. We can treat a bunch of values as one value if their type is 
a type tuple, so that's exactly what we do.

Then it's just a bit of string manipulation to get the right class names 
and overloads in the right places and we've generated a string of D code 
that does what we want. Mix it in and Bob's your uncle.

In your code, the line
  mixin(factory!MyClass);
should be inside an extern(C++) block, naturally.

The major caveat there: wherever you call "mixin(factory!MyClass);", you 
need MyClass to be in scope directly. If you have to refer to it with a 
qualified name, this will break. If that causes problems for you, you can 
use:

extern(C++) {
  {
    import mypkg.mymodule : MyClass;
    mixin(factory!MyClass);
  }
}

And that should import just that class for just that one block of code.


More information about the Digitalmars-d-learn mailing list