digitalmars.D.learn - Templates, constructors and default arguments
- aldanor (37/37) Dec 24 2014 I'm wondering how to best implement the following pattern: the
- ketmar via Digitalmars-d-learn (26/73) Dec 24 2014 On Thu, 25 Dec 2014 02:07:51 +0000
- aldanor (6/7) Dec 24 2014 Thanks once again! I think this mostly solves it. Would it be
- ketmar via Digitalmars-d-learn (21/29) Dec 24 2014 On Thu, 25 Dec 2014 03:07:55 +0000
I'm wondering how to best implement the following pattern: the constructor of a class has some required and some optional arguments; and one of the (optional) arguments also controls if any additional arguments should be passed. A hypothetical/simplified example that I came up with: there's a Dataset class which requires size and rank to be set. Size is required; rank defaults to 1. There's also a "filebacked" boolean option that defaults to false; if specified, a bunch of additional arguments are available (like filename, mode, etc), some of which have default values. Ideally, I'd want to be able to construct it like this: // "new Dataset" could instead be a static factory method like "Dataset.create" // this is is purely hypothetical new Dataset; // fails, size required new Dataset(size); // filebacked=false, rank=1 new Dataset(size, rank); // filebacked=false new Dataset(size, rank, "foo"); // fails, filename not applicable new Dataset!false(size); // rank=1 new Dataset!true(size, rank); // fails, filename missing new Dataset!true(size, rank, "foo"); // mode = "w+" new Dataset!true(size, rank, "foo", "w+"); If the "filebacked" argument only affects construction of the object and not its runtime behaviour, creating subclasses to solve this seems somewhat wrong. In fact, this argument doesn't even have to be a compile-time value but for the sake of being able to catch errors at compile time it probably should be. Templating the class like this class Dataset(filebacked = false) doesn't work since then "new Dataset(size)" is disallowed, in favor of "Dataset!()(size)". Adding a template factory function with variadic arg tuple like so Dataset create(bool filebacked = false, Args...)(uint size, uint rank = 1, Args args) doesn't work either because of the presence of default parameters ("default argument expected for args"). I wonder if there's any way to hack around this?
Dec 24 2014
On Thu, 25 Dec 2014 02:07:51 +0000 aldanor via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:I'm wondering how to best implement the following pattern: the=20 constructor of a class has some required and some optional=20 arguments; and one of the (optional) arguments also controls if=20 any additional arguments should be passed. =20 A hypothetical/simplified example that I came up with: there's a=20 Dataset class which requires size and rank to be set. Size is=20 required; rank defaults to 1. There's also a "filebacked" boolean=20 option that defaults to false; if specified, a bunch of=20 additional arguments are available (like filename, mode, etc),=20 some of which have default values. Ideally, I'd want to be able=20 to construct it like this: =20 // "new Dataset" could instead be a static factory method like=20 "Dataset.create" // this is is purely hypothetical new Dataset; // fails, size required new Dataset(size); // filebacked=3Dfalse, rank=3D1 new Dataset(size, rank); // filebacked=3Dfalse new Dataset(size, rank, "foo"); // fails, filename not applicable new Dataset!false(size); // rank=3D1 new Dataset!true(size, rank); // fails, filename missing new Dataset!true(size, rank, "foo"); // mode =3D "w+" new Dataset!true(size, rank, "foo", "w+"); =20 If the "filebacked" argument only affects construction of the=20 object and not its runtime behaviour, creating subclasses to=20 solve this seems somewhat wrong. In fact, this argument doesn't=20 even have to be a compile-time value but for the sake of being=20 able to catch errors at compile time it probably should be. =20 Templating the class like this =20 class Dataset(filebacked =3D false) =20 doesn't work since then "new Dataset(size)" is disallowed, in=20 favor of "Dataset!()(size)". =20 Adding a template factory function with variadic arg tuple like so =20 Dataset create(bool filebacked =3D false, Args...)(uint size,=20 uint rank =3D 1, Args args) =20 doesn't work either because of the presence of default parameters=20 ("default argument expected for args"). =20 I wonder if there's any way to hack around this?you can create two or more constrained templates, for example? like this: import iv.writer; void create(bool filebacked : false) (usize rank) { writefln!"filebacked=3Dfalse, rank=3D%s"(rank); } void create(bool filebacked : true) (usize rank, string fn, string mode= =3D"w+") { writefln!"filebacked=3Dtrue, rank=3D%s; fn=3D%s; mode=3D%s"(rank, fn, m= ode); } void create (usize rank=3D1) { writef!"rank=3D%s : "(rank); create!false(rank); } void main () { create(); // "rank=3D1 : filebacked=3Dfalse, rank=3D1" create(42); // "rank=3D42 : filebacked=3Dfalse, rank=3D42" create!false(66); // "filebacked=3Dfalse, rank=3D66" create!true(99, "t"); // "filebacked=3Dtrue, rank=3D99; fn=3Dt; mode=3D= w+" } happy hacking! ;-)
Dec 24 2014
On Thursday, 25 December 2014 at 02:28:47 UTC, ketmar via Digitalmars-d-learn wrote:happy hacking! ;-)Thanks once again! I think this mostly solves it. Would it be possible to somehow do the same trick with this()? (I guess due to having to write Type!() when default template arguments are omitted?)
Dec 24 2014
On Thu, 25 Dec 2014 03:07:55 +0000 aldanor via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:On Thursday, 25 December 2014 at 02:28:47 UTC, ketmar via=20 Digitalmars-d-learn wrote:unfortunately, you can have templated constructors, but you can't instantiate them manually. ;-) i.e. class A { this(T) () { ... } } can be compiled, but you can't call that constructor. there is simply no syntax for it. you still can do templated constructors with type deducing though: class A { this(T) (T arg) { ... } } auto n =3D new A(42); // this will call this!int(42) auto n =3D new A("alice"); // this will call this!string("alice") auto n =3D new A(true); // this will call this!bool(true) but you can't write: auto n =3D new A!bool(false); // will not compile the only thing you can do is make constructors private and using fabric. alas.happy hacking! ;-)=20 Thanks once again! I think this mostly solves it. Would it be=20 possible to somehow do the same trick with this()? (I guess due=20 to having to write Type!() when default template arguments are=20 omitted?)
Dec 24 2014