Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
March 02, 2016 Template mixins and struct constructors | ||||
---|---|---|---|---|
| ||||
I can do this: struct Foo { int a; string b; this(int a) { this.a = a; } this(Args...)(string b, auto ref Args args) { this.b = b; this(args); } } unittest { auto foo1 = Foo(5); auto foo2 = Foo("foo", 15); } However, the following code is invalid: mixin template AddField(T) { T b; this(Args...)(T b, auto ref Args args) { this.b = b; this(args); } } struct Bar { mixin AddField!string; int a; this(int a) { this.a = a; } } unittest { auto bar1 = Bar(5); auto bar2 = Bar("bar", 15); // line 31 } sctor.d(31): Error: constructor sctor.Bar.this (int a) is not callable using argument types (string, int) Is it by design or is it a bug? And, if it is by design, what is the reason for that? |
March 02, 2016 Re: Template mixins and struct constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adrian Matoga | On Wednesday, 2 March 2016 at 12:27:04 UTC, Adrian Matoga wrote:
> I can do this:
>
> struct Foo {
> int a;
> string b;
> this(int a) { this.a = a; }
> this(Args...)(string b, auto ref Args args) { this.b = b; this(args); }
> }
>
> unittest {
> auto foo1 = Foo(5);
> auto foo2 = Foo("foo", 15);
> }
>
> However, the following code is invalid:
>
> mixin template AddField(T) {
> T b;
> this(Args...)(T b, auto ref Args args)
> {
> this.b = b;
> this(args);
> }
> }
>
> struct Bar {
> mixin AddField!string;
> int a;
> this(int a) { this.a = a; }
> }
>
> unittest {
> auto bar1 = Bar(5);
> auto bar2 = Bar("bar", 15); // line 31
> }
>
> sctor.d(31): Error: constructor sctor.Bar.this (int a) is not callable using argument types (string, int)
>
> Is it by design or is it a bug?
> And, if it is by design, what is the reason for that?
You can use string mixins:
template AddField(T) {
enum AddField = T.stringof ~ ` b;
this(Args...)(` ~ T.stringof ~ ` b, auto ref Args args)
{
this.b = b;
this(args);
}`;
}
struct Bar {
mixin(AddField!string);
int a;
this(int a) { this.a = a; }
}
unittest {
auto bar1 = Bar(5);
auto bar2 = Bar("bar", 15); // line 31
}
|
March 02, 2016 Re: Template mixins and struct constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adrian Matoga | On Wednesday, 2 March 2016 at 12:27:04 UTC, Adrian Matoga wrote:
> I can do this:
>
> struct Foo {
> int a;
> string b;
> this(int a) { this.a = a; }
> this(Args...)(string b, auto ref Args args) { this.b = b; this(args); }
> }
>
> unittest {
> auto foo1 = Foo(5);
> auto foo2 = Foo("foo", 15);
> }
>
> However, the following code is invalid:
>
> mixin template AddField(T) {
> T b;
> this(Args...)(T b, auto ref Args args)
> {
> this.b = b;
> this(args);
> }
> }
>
> struct Bar {
> mixin AddField!string;
> int a;
> this(int a) { this.a = a; }
> }
>
> unittest {
> auto bar1 = Bar(5);
> auto bar2 = Bar("bar", 15); // line 31
> }
>
> sctor.d(31): Error: constructor sctor.Bar.this (int a) is not callable using argument types (string, int)
>
> Is it by design or is it a bug?
> And, if it is by design, what is the reason for that?
I would say it is by design. What this will generate is something like:
struct Bar {
static struct _scope {
string b;
this(Args...)(string b, auto ref Args args) {
this.b = b; this(args);
}
}
int a;
this(int a) { this.a = a; }
}
|
March 02, 2016 Re: Template mixins and struct constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Kozak | On Wednesday, 2 March 2016 at 12:48:47 UTC, Daniel Kozak wrote:
> On Wednesday, 2 March 2016 at 12:27:04 UTC, Adrian Matoga wrote:
>> (...)
>
> You can use string mixins:
>
> template AddField(T) {
> enum AddField = T.stringof ~ ` b;
> this(Args...)(` ~ T.stringof ~ ` b, auto ref Args args)
> {
> this.b = b;
> this(args);
> }`;
> }
>
> struct Bar {
> mixin(AddField!string);
> int a;
> this(int a) { this.a = a; }
> }
>
> unittest {
> auto bar1 = Bar(5);
> auto bar2 = Bar("bar", 15); // line 31
> }
What if T is private type in some other module or, even worse, a Voldemort type?
|
March 02, 2016 Re: Template mixins and struct constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adrian Matoga | On Wednesday, 2 March 2016 at 13:18:23 UTC, Adrian Matoga wrote:
> On Wednesday, 2 March 2016 at 12:48:47 UTC, Daniel Kozak wrote:
>> On Wednesday, 2 March 2016 at 12:27:04 UTC, Adrian Matoga wrote:
>>> (...)
>>
>> You can use string mixins:
>>
>> template AddField(T) {
>> enum AddField = T.stringof ~ ` b;
>> this(Args...)(` ~ T.stringof ~ ` b, auto ref Args args)
>> {
>> this.b = b;
>> this(args);
>> }`;
>> }
>>
>> struct Bar {
>> mixin(AddField!string);
>> int a;
>> this(int a) { this.a = a; }
>> }
>>
>> unittest {
>> auto bar1 = Bar(5);
>> auto bar2 = Bar("bar", 15); // line 31
>> }
>
> What if T is private type in some other module or, even worse, a Voldemort type?
OK maybe this one:
template AddField(T) {
T b;
this(Args...)(T b, auto ref Args args)
{
this.b = b;
this(args);
}
this(int a) {
this.a = a;
}
}
struct Bar {
int a;
mixin AddField!(string);
}
unittest {
auto bar1 = Bar(5);
auto bar2 = Bar("bar", 15);
}
|
March 02, 2016 Re: Template mixins and struct constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Kozak | On Wednesday, 2 March 2016 at 14:36:59 UTC, Daniel Kozak wrote:
> OK maybe this one:
>
> template AddField(T) {
> T b;
> this(Args...)(T b, auto ref Args args)
> {
> this.b = b;
> this(args);
> }
> this(int a) {
> this.a = a;
> }
> }
>
> struct Bar {
> int a;
> mixin AddField!(string);
> }
>
> unittest {
> auto bar1 = Bar(5);
> auto bar2 = Bar("bar", 15);
> }
Then it's limited to structs in which only "int a" is to be initialized. Not very useful and the templated ctor is not needed now.
struct Baz {
mixin AddField!string; // fail, no "int a" in Baz.
ulong d;
double x;
string foo;
}
|
March 02, 2016 Re: Template mixins and struct constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adrian Matoga | On Wednesday, 2 March 2016 at 14:50:15 UTC, Adrian Matoga wrote:
> On Wednesday, 2 March 2016 at 14:36:59 UTC, Daniel Kozak wrote:
>> OK maybe this one:
>>
>> template AddField(T) {
>> T b;
>> this(Args...)(T b, auto ref Args args)
>> {
>> this.b = b;
>> this(args);
>> }
>> this(int a) {
>> this.a = a;
>> }
>> }
>>
>> struct Bar {
>> int a;
>> mixin AddField!(string);
>> }
>>
>> unittest {
>> auto bar1 = Bar(5);
>> auto bar2 = Bar("bar", 15);
>> }
>
> Then it's limited to structs in which only "int a" is to be initialized. Not very useful and the templated ctor is not needed now.
>
> struct Baz {
> mixin AddField!string; // fail, no "int a" in Baz.
> ulong d;
> double x;
> string foo;
> }
OK then:
mixin template AddField(T) {
T b;
auto ref constructor(Args...)(T b, auto ref Args args)
{
typeof(this) r;
r.b = b;
r.__ctor(args);
return r;
}
}
struct Bar {
mixin AddField!string;
int a;
this(int a) { this.a = a; }
alias __ctor = constructor;
}
unittest {
import std.stdio;
auto bar1 = Bar(5);
auto bar2 = Bar("bar", 15);
writeln(bar1);
writeln(bar2);
}
|
March 02, 2016 Re: Template mixins and struct constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adrian Matoga | On Wednesday, 2 March 2016 at 12:27:04 UTC, Adrian Matoga wrote: > Is it by design or is it a bug? > And, if it is by design, what is the reason for that? That's by design. It allows you to override names from a template mixin like inheritance but no runtime cost. Read my tip of the week here to see how it works and how you can combine ctors from a mixin: http://arsdnet.net/this-week-in-d/2016-feb-07.html |
March 02, 2016 Re: Template mixins and struct constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe |
Dne 2.3.2016 v 21:39 Adam D. Ruppe via Digitalmars-d-learn napsal(a):
> On Wednesday, 2 March 2016 at 12:27:04 UTC, Adrian Matoga wrote:
>> Is it by design or is it a bug?
>> And, if it is by design, what is the reason for that?
>
> That's by design. It allows you to override names from a template mixin like inheritance but no runtime cost.
>
> Read my tip of the week here to see how it works and how you can combine ctors from a mixin:
>
> http://arsdnet.net/this-week-in-d/2016-feb-07.html
I know it :). I need to upgrade my memory. I spent all day looking for it in D cookbook, because I was sure it was you who make this tip somewhere.
|
March 03, 2016 Re: Template mixins and struct constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On Wednesday, 2 March 2016 at 20:39:57 UTC, Adam D. Ruppe wrote:
> On Wednesday, 2 March 2016 at 12:27:04 UTC, Adrian Matoga wrote:
>> Is it by design or is it a bug?
>> And, if it is by design, what is the reason for that?
>
> That's by design. It allows you to override names from a template mixin like inheritance but no runtime cost.
>
> Read my tip of the week here to see how it works and how you can combine ctors from a mixin:
>
> http://arsdnet.net/this-week-in-d/2016-feb-07.html
Ah, I was on vacation at that time so that's why I don't remember reading it. :)
Thanks! It's a nice workaround but it's, well, a workaround. It leaks the internals of the template mixin and a potential API user would have to remember two additional quirks when using it. I guess I'll try a different approach, initializing the mixed in members later with a function.
|
Copyright © 1999-2021 by the D Language Foundation