www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Template Base Classes, Refering to typeof(this)

reply Travis Boucher <boucher.travis gmail.com> writes:
I am writing a generic vector base class.  The class implements all of 
the operator overloads so I don't have to implement them over and over 
and over for each type of vector class.

class VectorBase(size_t S, T) {
	T[S] data;

	...
}

class Vector3f : VectorBase!(3, float) { ... }

The problem I am having is implementing operations that can take a 
matching vector.  I can't figure out the proper way of declaring the 
type of input.

eg.

void opAssign(VectorBase!(S, T) r);
 function VectorBase!(3LU,float).VectorBase.opAssign identity 

void opAssign(this r);
 basic type expected, not this

The only way I can think of handling it is to add another parameter to the template declaration, eg: class VectorBase(size_t S, T, N) { ... } class Vector3f : VectorBase!(3, float, Vector3f) { ... } But I would like to avoid that if possible. Any hints on how to implement this so I can keep my original declaration? class VectorBase(size_t S, T)
Nov 04 2009
next sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Travis Boucher wrote:
 
 Any hints on how to implement this so I can keep my original
 declaration? class VectorBase(size_t S, T)

Make that bugger a struct or forget about opAssign.
Nov 04 2009
parent reply Travis Boucher <boucher.travis gmail.com> writes:
Ellery Newcomer wrote:
 Travis Boucher wrote:
 Any hints on how to implement this so I can keep my original
 declaration? class VectorBase(size_t S, T)

Make that bugger a struct or forget about opAssign.

Why wouldn't opAssign work for a class? (I don't have a problem with structs, they make more sense for a small (2-5) Vector class anyway.) From what I understand, structs can't inherit from other structs. I could implement the specific classes using template mixins if needed.
Nov 04 2009
parent BCS <none anon.com> writes:
Hello Travis,

 Ellery Newcomer wrote:
 
 Travis Boucher wrote:
 
 Any hints on how to implement this so I can keep my original
 declaration? class VectorBase(size_t S, T)
 


structs, they make more sense for a small (2-5) Vector class anyway.) From what I understand, structs can't inherit from other structs. I could implement the specific classes using template mixins if needed.

//given: Class c, d; c=d; // this is *always* a reference copy.
Nov 04 2009
prev sibling next sibling parent reply "Robert Jacques" <sandford jhu.edu> writes:
On Wed, 04 Nov 2009 13:35:45 -0500, Travis Boucher  
<boucher.travis gmail.com> wrote:

 I am writing a generic vector base class.  The class implements all of  
 the operator overloads so I don't have to implement them over and over  
 and over for each type of vector class.

 class VectorBase(size_t S, T) {
 	T[S] data;

 	...
 }

 class Vector3f : VectorBase!(3, float) { ... }

 The problem I am having is implementing operations that can take a  
 matching vector.  I can't figure out the proper way of declaring the  
 type of input.

 eg.

 void opAssign(VectorBase!(S, T) r);
  > function VectorBase!(3LU,float).VectorBase.opAssign identity  
 assignment operator overload is illegal


 void opAssign(this r);
  > basic type expected, not this


 The only way I can think of handling it is to add another parameter to  
 the template declaration, eg:

 class VectorBase(size_t S, T, N) { ... }
 class Vector3f : VectorBase!(3, float, Vector3f) { ... }

 But I would like to avoid that if possible.

 Any hints on how to implement this so I can keep my original  
 declaration? class VectorBase(size_t S, T)

Well first, you can't overload assignment of a class to it's own type. (It's part of the language spec, at the bottom of the operator overload page IIRC) Second, I've already solved this in D2, (using structs) so let me know if you want code. Third, fixed sized arrays as value-type are coming in the next release (I think), so you could wait for that. Lastly, you're (probably) going to run into issues with your other operator overloads because of some bugs in instantiating templates inside of templates using template literals as opposed to types.
Nov 04 2009
parent Travis Boucher <boucher.travis gmail.com> writes:
Robert Jacques wrote:
 On Wed, 04 Nov 2009 13:35:45 -0500, Travis Boucher 
 <boucher.travis gmail.com> wrote:
 
 I am writing a generic vector base class.  The class implements all of 
 the operator overloads so I don't have to implement them over and over 
 and over for each type of vector class.

 class VectorBase(size_t S, T) {
     T[S] data;

     ...
 }

 class Vector3f : VectorBase!(3, float) { ... }

 The problem I am having is implementing operations that can take a 
 matching vector.  I can't figure out the proper way of declaring the 
 type of input.

 eg.

 void opAssign(VectorBase!(S, T) r);
  > function VectorBase!(3LU,float).VectorBase.opAssign identity 
 assignment operator overload is illegal


 void opAssign(this r);
  > basic type expected, not this


 The only way I can think of handling it is to add another parameter to 
 the template declaration, eg:

 class VectorBase(size_t S, T, N) { ... }
 class Vector3f : VectorBase!(3, float, Vector3f) { ... }

 But I would like to avoid that if possible.

 Any hints on how to implement this so I can keep my original 
 declaration? class VectorBase(size_t S, T)

Well first, you can't overload assignment of a class to it's own type.

Ok, that makes sense, since an object is just a reference, so an assignment is really just a pointer copy, not a data copy, correct?
 (It's part of the language spec, at the bottom of the operator overload 
 page IIRC) Second, I've already solved this in D2, (using structs) so 
 let me know if you want code. 

Yeah, I'd be interested. I am currently running gdc with D1, but I did see some notes on getting gdc working with D2.
 Third, fixed sized arrays as value-type 
 are coming in the next release (I think), so you could wait for that. 
 Lastly, you're (probably) going to run into issues with your other 
 operator overloads because of some bugs in instantiating templates 
 inside of templates using template literals as opposed to types.

Do you have any hints on what to look out for? I did implement a Vector class template, passing in a template parameter to refer to the instantiated type. It used mixins. eg. class VectorBase(size_t S, T, N) { ... } class Vector3f {mixin VectorBase!(3, float, Vector3f); } It compiled and worked for the basic tests, including all operator overloading. auto a = new Vector3f(); auto b = new Vector3f(1, 2, 3); auto c = b * 2; // c = Vector3f(2, 4, 6) auto d = b + c; // d = Vector3f(3, 6, 9) I didn't run into any bugs, and even more complex methods (explict methods) returned valid results (eg. T dotProduct(N vec) { ... }).
Nov 04 2009
prev sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Wed, 04 Nov 2009 15:31:16 -0500, Travis Boucher  
<boucher.travis gmail.com> wrote:

 Robert Jacques wrote:
 On Wed, 04 Nov 2009 13:35:45 -0500, Travis Boucher  
 <boucher.travis gmail.com> wrote:

 I am writing a generic vector base class.  The class implements all of  
 the operator overloads so I don't have to implement them over and over  
 and over for each type of vector class.

 class VectorBase(size_t S, T) {
     T[S] data;

     ...
 }

 class Vector3f : VectorBase!(3, float) { ... }

 The problem I am having is implementing operations that can take a  
 matching vector.  I can't figure out the proper way of declaring the  
 type of input.

 eg.

 void opAssign(VectorBase!(S, T) r);
  > function VectorBase!(3LU,float).VectorBase.opAssign identity  
 assignment operator overload is illegal


 void opAssign(this r);
  > basic type expected, not this


 The only way I can think of handling it is to add another parameter to  
 the template declaration, eg:

 class VectorBase(size_t S, T, N) { ... }
 class Vector3f : VectorBase!(3, float, Vector3f) { ... }

 But I would like to avoid that if possible.

 Any hints on how to implement this so I can keep my original  
 declaration? class VectorBase(size_t S, T)


Ok, that makes sense, since an object is just a reference, so an assignment is really just a pointer copy, not a data copy, correct?
 (It's part of the language spec, at the bottom of the operator overload  
 page IIRC) Second, I've already solved this in D2, (using structs) so  
 let me know if you want code.

Yeah, I'd be interested. I am currently running gdc with D1, but I did see some notes on getting gdc working with D2.
 Third, fixed sized arrays as value-type are coming in the next release  
 (I think), so you could wait for that. Lastly, you're (probably) going  
 to run into issues with your other operator overloads because of some  
 bugs in instantiating templates inside of templates using template  
 literals as opposed to types.

Do you have any hints on what to look out for? I did implement a Vector class template, passing in a template parameter to refer to the instantiated type. It used mixins. eg. class VectorBase(size_t S, T, N) { ... } class Vector3f {mixin VectorBase!(3, float, Vector3f); } It compiled and worked for the basic tests, including all operator overloading. auto a = new Vector3f(); auto b = new Vector3f(1, 2, 3); auto c = b * 2; // c = Vector3f(2, 4, 6) auto d = b + c; // d = Vector3f(3, 6, 9) I didn't run into any bugs, and even more complex methods (explict methods) returned valid results (eg. T dotProduct(N vec) { ... }).

There's a bug with returning VectorBase!(S,T,N) from inside VectorBase(size_t S, T, N) { ... }; see the bugzilla for a test case and more details http://d.puremagic.com/issues/show_bug.cgi?id=2257. My first implementation also used mixins without any problems, I only ran into issues when I switched to templated functions.
Nov 04 2009