Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
August 08, 2013 Virtual templates members | ||||
---|---|---|---|---|
| ||||
The following code is used to reduce dependence on new and the GC. iNew is used as the replacement. The problem is, where ever New is used, it requires typing the type twice. e.g., A.New!A(...) instead of A.New(...) Is there any way to solve this issue? (iNew is suppose to provide the contract to implement a "new" like method that will allocate the class. Note there is no virtual function so no overhead) import std.stdio, std.conv; enum eNew { Default = 0, } interface iNew { final static T New(T, A...)(A args) { eNew type = eNew.Default; static if (A.length == 0 || !is(typeof(args[0]) == eNew)) alias nargs = args; else { type = cast(eNew)args[0]; alias nargs = args[1..$]; } writeln(">> ", __traits(classInstanceSize, T)); switch (type) { default: return new T(nargs); } return new T(nargs); } } class A : iNew { int t; } class B : A { int q; double d; } void main() { A a = A.New!A(); B b = B.New!B(); readln(); } |
August 08, 2013 Re: Virtual templates members | ||||
---|---|---|---|---|
| ||||
Posted in reply to JS | On Thursday, 8 August 2013 at 01:48:49 UTC, JS wrote:
> The following code is used to reduce dependence on new and the GC. iNew is used as the replacement.
>
> The problem is, where ever New is used, it requires typing the type twice.
>
> e.g.,
>
> A.New!A(...)
>
> instead of A.New(...)
>
> Is there any way to solve this issue?
>
> (iNew is suppose to provide the contract to implement a "new" like method that will allocate the class. Note there is no virtual function so no overhead)
>
>
> import std.stdio, std.conv;
>
> enum eNew
> {
> Default = 0,
> }
>
> interface iNew
> {
>
> final static T New(T, A...)(A args)
> {
> eNew type = eNew.Default;
> static if (A.length == 0 || !is(typeof(args[0]) == eNew))
> alias nargs = args;
> else
> {
> type = cast(eNew)args[0];
> alias nargs = args[1..$];
> }
>
> writeln(">> ", __traits(classInstanceSize, T));
>
> switch (type)
> {
> default: return new T(nargs);
> }
>
> return new T(nargs);
> }
> }
>
> class A : iNew
> {
> int t;
> }
>
> class B : A
> {
> int q;
> double d;
> }
>
> void main()
> {
> A a = A.New!A();
> B b = B.New!B();
> readln();
> }
Why not make it a mixin template?
---
import std.stdio, std.conv;
enum eNew
{
Default = 0,
}
mixin template iNew(T)
{
final static T New(A...)(A args)
{
eNew type = eNew.Default;
static if (A.length == 0 || !is(typeof(args[0]) == eNew))
alias nargs = args;
else
{
type = cast(eNew)args[0];
alias nargs = args[1..$];
}
writeln(">> ", __traits(classInstanceSize, T));
switch (type)
{
default: return new T(nargs);
}
//return new T(nargs);
}
}
class A
{
mixin iNew!A;
int t;
}
class B : A
{
mixin iNew!B;
int q;
double d;
}
void main()
{
A a = A.New();
B b = B.New();
readln();
}
---
|
August 08, 2013 Re: Virtual templates members | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicolas Sicard | On Thursday, 8 August 2013 at 07:21:19 UTC, Nicolas Sicard wrote:
> On Thursday, 8 August 2013 at 01:48:49 UTC, JS wrote:
>> The following code is used to reduce dependence on new and the GC. iNew is used as the replacement.
>>
>> The problem is, where ever New is used, it requires typing the type twice.
>>
>> e.g.,
>>
>> A.New!A(...)
>>
>> instead of A.New(...)
>>
>> Is there any way to solve this issue?
>>
>> (iNew is suppose to provide the contract to implement a "new" like method that will allocate the class. Note there is no virtual function so no overhead)
>>
>>
>> import std.stdio, std.conv;
>>
>> enum eNew
>> {
>> Default = 0,
>> }
>>
>> interface iNew
>> {
>>
>> final static T New(T, A...)(A args)
>> {
>> eNew type = eNew.Default;
>> static if (A.length == 0 || !is(typeof(args[0]) == eNew))
>> alias nargs = args;
>> else
>> {
>> type = cast(eNew)args[0];
>> alias nargs = args[1..$];
>> }
>>
>> writeln(">> ", __traits(classInstanceSize, T));
>>
>> switch (type)
>> {
>> default: return new T(nargs);
>> }
>>
>> return new T(nargs);
>> }
>> }
>>
>> class A : iNew
>> {
>> int t;
>> }
>>
>> class B : A
>> {
>> int q;
>> double d;
>> }
>>
>> void main()
>> {
>> A a = A.New!A();
>> B b = B.New!B();
>> readln();
>> }
>
> Why not make it a mixin template?
> ---
> import std.stdio, std.conv;
>
> enum eNew
> {
> Default = 0,
> }
>
> mixin template iNew(T)
> {
> final static T New(A...)(A args)
> {
> eNew type = eNew.Default;
> static if (A.length == 0 || !is(typeof(args[0]) == eNew))
> alias nargs = args;
> else
> {
> type = cast(eNew)args[0];
> alias nargs = args[1..$];
> }
>
> writeln(">> ", __traits(classInstanceSize, T));
>
> switch (type)
> {
> default: return new T(nargs);
> }
>
> //return new T(nargs);
> }
> }
>
> class A
> {
> mixin iNew!A;
> int t;
> }
>
> class B : A
> {
> mixin iNew!B;
> int q;
> double d;
> }
>
> void main()
> {
> A a = A.New();
> B b = B.New();
> readln();
> }
> ---
Because I don't want to have to specify this in each class. iNew is suppose to be a contract. What happens if someone writes a class and forgets to add the mixin then distributes the class in a library? There's no issue with that using an interface because it results in an error.
|
August 08, 2013 Re: Virtual templates members | ||||
---|---|---|---|---|
| ||||
Posted in reply to JS | On Thursday, 8 August 2013 at 16:58:37 UTC, JS wrote:
> On Thursday, 8 August 2013 at 07:21:19 UTC, Nicolas Sicard wrote:
>> On Thursday, 8 August 2013 at 01:48:49 UTC, JS wrote:
>>> The following code is used to reduce dependence on new and the GC. iNew is used as the replacement.
>>>
>>> The problem is, where ever New is used, it requires typing the type twice.
>>>
>>> e.g.,
>>>
>>> A.New!A(...)
>>>
>>> instead of A.New(...)
>>>
>>> Is there any way to solve this issue?
>>>
>>> (iNew is suppose to provide the contract to implement a "new" like method that will allocate the class. Note there is no virtual function so no overhead)
>>>
>>>
>>> import std.stdio, std.conv;
>>>
>>> enum eNew
>>> {
>>> Default = 0,
>>> }
>>>
>>> interface iNew
>>> {
>>>
>>> final static T New(T, A...)(A args)
>>> {
>>> eNew type = eNew.Default;
>>> static if (A.length == 0 || !is(typeof(args[0]) == eNew))
>>> alias nargs = args;
>>> else
>>> {
>>> type = cast(eNew)args[0];
>>> alias nargs = args[1..$];
>>> }
>>>
>>> writeln(">> ", __traits(classInstanceSize, T));
>>>
>>> switch (type)
>>> {
>>> default: return new T(nargs);
>>> }
>>>
>>> return new T(nargs);
>>> }
>>> }
>>>
>>> class A : iNew
>>> {
>>> int t;
>>> }
>>>
>>> class B : A
>>> {
>>> int q;
>>> double d;
>>> }
>>>
>>> void main()
>>> {
>>> A a = A.New!A();
>>> B b = B.New!B();
>>> readln();
>>> }
>>
>> Why not make it a mixin template?
>> ---
>> import std.stdio, std.conv;
>>
>> enum eNew
>> {
>> Default = 0,
>> }
>>
>> mixin template iNew(T)
>> {
>> final static T New(A...)(A args)
>> {
>> eNew type = eNew.Default;
>> static if (A.length == 0 || !is(typeof(args[0]) == eNew))
>> alias nargs = args;
>> else
>> {
>> type = cast(eNew)args[0];
>> alias nargs = args[1..$];
>> }
>>
>> writeln(">> ", __traits(classInstanceSize, T));
>>
>> switch (type)
>> {
>> default: return new T(nargs);
>> }
>>
>> //return new T(nargs);
>> }
>> }
>>
>> class A
>> {
>> mixin iNew!A;
>> int t;
>> }
>>
>> class B : A
>> {
>> mixin iNew!B;
>> int q;
>> double d;
>> }
>>
>> void main()
>> {
>> A a = A.New();
>> B b = B.New();
>> readln();
>> }
>> ---
>
> Because I don't want to have to specify this in each class. iNew is suppose to be a contract. What happens if someone writes a class and forgets to add the mixin then distributes the class in a library? There's no issue with that using an interface because it results in an error.
I understand the goal. But if someone forgets to add the mixin, A.New() would not compile. And the probability of mistakenly calling 'new A' might even be as high as the probability of forgetting the mixin.
|
August 08, 2013 Re: Virtual templates members | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicolas Sicard | On Thursday, 8 August 2013 at 17:32:56 UTC, Nicolas Sicard wrote:
> On Thursday, 8 August 2013 at 16:58:37 UTC, JS wrote:
>> On Thursday, 8 August 2013 at 07:21:19 UTC, Nicolas Sicard wrote:
>>> On Thursday, 8 August 2013 at 01:48:49 UTC, JS wrote:
>>>> The following code is used to reduce dependence on new and the GC. iNew is used as the replacement.
>>>>
>>>> The problem is, where ever New is used, it requires typing the type twice.
>>>>
>>>> e.g.,
>>>>
>>>> A.New!A(...)
>>>>
>>>> instead of A.New(...)
>>>>
>>>> Is there any way to solve this issue?
>>>>
>>>> (iNew is suppose to provide the contract to implement a "new" like method that will allocate the class. Note there is no virtual function so no overhead)
>>>>
>>>>
>>>> import std.stdio, std.conv;
>>>>
>>>> enum eNew
>>>> {
>>>> Default = 0,
>>>> }
>>>>
>>>> interface iNew
>>>> {
>>>>
>>>> final static T New(T, A...)(A args)
>>>> {
>>>> eNew type = eNew.Default;
>>>> static if (A.length == 0 || !is(typeof(args[0]) == eNew))
>>>> alias nargs = args;
>>>> else
>>>> {
>>>> type = cast(eNew)args[0];
>>>> alias nargs = args[1..$];
>>>> }
>>>>
>>>> writeln(">> ", __traits(classInstanceSize, T));
>>>>
>>>> switch (type)
>>>> {
>>>> default: return new T(nargs);
>>>> }
>>>>
>>>> return new T(nargs);
>>>> }
>>>> }
>>>>
>>>> class A : iNew
>>>> {
>>>> int t;
>>>> }
>>>>
>>>> class B : A
>>>> {
>>>> int q;
>>>> double d;
>>>> }
>>>>
>>>> void main()
>>>> {
>>>> A a = A.New!A();
>>>> B b = B.New!B();
>>>> readln();
>>>> }
>>>
>>> Why not make it a mixin template?
>>> ---
>>> import std.stdio, std.conv;
>>>
>>> enum eNew
>>> {
>>> Default = 0,
>>> }
>>>
>>> mixin template iNew(T)
>>> {
>>> final static T New(A...)(A args)
>>> {
>>> eNew type = eNew.Default;
>>> static if (A.length == 0 || !is(typeof(args[0]) == eNew))
>>> alias nargs = args;
>>> else
>>> {
>>> type = cast(eNew)args[0];
>>> alias nargs = args[1..$];
>>> }
>>>
>>> writeln(">> ", __traits(classInstanceSize, T));
>>>
>>> switch (type)
>>> {
>>> default: return new T(nargs);
>>> }
>>>
>>> //return new T(nargs);
>>> }
>>> }
>>>
>>> class A
>>> {
>>> mixin iNew!A;
>>> int t;
>>> }
>>>
>>> class B : A
>>> {
>>> mixin iNew!B;
>>> int q;
>>> double d;
>>> }
>>>
>>> void main()
>>> {
>>> A a = A.New();
>>> B b = B.New();
>>> readln();
>>> }
>>> ---
>>
>> Because I don't want to have to specify this in each class. iNew is suppose to be a contract. What happens if someone writes a class and forgets to add the mixin then distributes the class in a library? There's no issue with that using an interface because it results in an error.
>
> I understand the goal. But if someone forgets to add the mixin, A.New() would not compile. And the probability of mistakenly calling 'new A' might even be as high as the probability of forgetting the mixin.
But it is backwards. If you are designing a class and forget, then distribute a library of that class, everyone is screwed if you forget to include the appropriate member. Not only will they not be able to call it, as you said, they won't easily be able to fix it.
With interfaces, it provides the contract. With the static final, it provides a single instance(doesn't have to mixin at each class).
I realize it probably doesn't matter too much in the long run but I'm asking how to make what I want work and not a workaround.
It would be nice to have a This which returns the type of the interface, analogous to this, which returns the instance.
After all, I could just write a standard template and use that regardless and call it directly. Then there is no need to use mixins which waste space.
e.g.,
T New(T, A...)(A args) { }
Then just
New!A(...)
but then I loose my interface contract, which, in this scenario isn't a huge deal but I'd like to be able to distinguish objects that have this allocation strategy pattern vs those that don't. In the future, I may want to allow the class to provide it's own allocation scheme overriding iNew.New(indirectly).
|
August 08, 2013 Re: Virtual templates members | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicolas Sicard | Actually "mixin New!()" should be enough, as typeof(this) resolves to enclosing type in template mixins. And inheritance brings nothing over mixins in terms of guarantees - forgetting to use proper Base or use proper method is almost the same level of accident. |
Copyright © 1999-2021 by the D Language Foundation