Virtual templates members

JS js.mdnq at gmail.com
Thu Aug 8 11:01:16 PDT 2013


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).



More information about the Digitalmars-d-learn mailing list