digitalmars.D.learn - Template bug?
- Artyom Shalkhakov <artyom.sh gmail.ru> Jan 29 2007
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Jan 29 2007
- Artyom Shalkhakov <artyom.sh gmail.ru> Jan 29 2007
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Jan 30 2007
- Frits van Bommel <fvbommel REMwOVExCAPSs.nl> Jan 30 2007
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Jan 30 2007
Hello everyone.
I have a problem regarding D templates.
This code doesn't work. I would like to know how do I get it up'n'running?
struct temp_t( type ) {
void setOwner( type *newOwner ) {
owner = newOwner;
}
type *getOwner() {
return owner;
}
protected {
temp_t * head;
temp_t * next;
temp_t * prev;
type * owner;
}
}
class testClass_t {
this( int d ) {
data = d;
tst.setOwner( &this );
}
int data;
temp_t!( testClass_t ) tst;
}
void foo() {
testClass_t bar = new testClass_t( 0x1234 );
// what is the difference between '==' and 'is'?
assert( ( *bar ).getOwner == bar ); // doesn't work
}
Can anyone tell me what is wrong? Thanks in advance.
PS Excuse me for my English, as it's not my native language.
Jan 29 2007
"Artyom Shalkhakov" <artyom.sh gmail.ru> wrote in message news:epmho3$282d$1 digitaldaemon.com...Hello everyone. I have a problem regarding D templates. This code doesn't work. I would like to know how do I get it up'n'running? struct temp_t( type ) { void setOwner( type *newOwner ) { owner = newOwner; } type *getOwner() { return owner; } protected { temp_t * head; temp_t * next; temp_t * prev; type * owner; } } class testClass_t { this( int d ) { data = d; tst.setOwner( &this ); } int data; temp_t!( testClass_t ) tst; } void foo() { testClass_t bar = new testClass_t( 0x1234 ); // what is the difference between '==' and 'is'? assert( ( *bar ).getOwner == bar ); // doesn't work }
There are a few things going wrong. One, when you write "tst.setOwner( &this );", this sets the owner to the address of a local variable. This is a Bad Thing. Remember that classes are reference types, so they are implicitly pointers. So instead of making your struct use pointers, just take all the *s out. struct temp_t( type ) { void setOwner( type newOwner ) { owner = newOwner; } type getOwner() { return owner; } protected { temp_t * head; temp_t * next; temp_t * prev; type owner; } } Then in your class's constructor, use tst.setOwner( this ); Lastly, this line: assert( ( *bar ).getOwner == bar ); Doesn't even compile because (1) you cannot dereference bar because it's not a pointer, it's a reference, and (2) there is no .getOwner property for the testClass_t class. Instead, you should use: assert( bar.tst.getOwner is bar); And that brings me to my last point, the difference between 'is' and '=='. 'is' is used to see if two references (or pointers) point to the same location. '==' is used to see if two things are equal. If you have two class references, a and b, and you write a == b This is the same as writing a.opEquals(b) If a is null, this will get you a segfault. However, if you just want to see if a and b are pointing to the same instance, use a is b Which is what you want to do in your example.
Jan 29 2007
Jarrett Billingsley Wrote:"Artyom Shalkhakov" <artyom.sh gmail.ru> wrote in message news:epmho3$282d$1 digitaldaemon.com...Hello everyone. I have a problem regarding D templates. This code doesn't work. I would like to know how do I get it up'n'running? struct temp_t( type ) { void setOwner( type *newOwner ) { owner = newOwner; } type *getOwner() { return owner; } protected { temp_t * head; temp_t * next; temp_t * prev; type * owner; } } class testClass_t { this( int d ) { data = d; tst.setOwner( &this ); } int data; temp_t!( testClass_t ) tst; } void foo() { testClass_t bar = new testClass_t( 0x1234 ); // what is the difference between '==' and 'is'? assert( ( *bar ).getOwner == bar ); // doesn't work }
There are a few things going wrong. One, when you write "tst.setOwner( &this );", this sets the owner to the address of a local variable. This is a Bad Thing. Remember that classes are reference types, so they are implicitly pointers. So instead of making your struct use pointers, just take all the *s out. struct temp_t( type ) { void setOwner( type newOwner ) { owner = newOwner; } type getOwner() { return owner; } protected { temp_t * head; temp_t * next; temp_t * prev; type owner; } } Then in your class's constructor, use tst.setOwner( this ); Lastly, this line: assert( ( *bar ).getOwner == bar ); Doesn't even compile because (1) you cannot dereference bar because it's not a pointer, it's a reference, and (2) there is no .getOwner property for the testClass_t class. Instead, you should use: assert( bar.tst.getOwner is bar); And that brings me to my last point, the difference between 'is' and '=='. 'is' is used to see if two references (or pointers) point to the same location. '==' is used to see if two things are equal. If you have two class references, a and b, and you write a == b This is the same as writing a.opEquals(b) If a is null, this will get you a segfault. However, if you just want to see if a and b are pointing to the same instance, use a is b Which is what you want to do in your example.
Thanks for your answer. Yes, it was my mistake to write it out like this:assert( ( *bar ).getOwner == bar );
Well, this is my bug :) tst.setOwner( &this ); Okay, I've tried to use pointer to class because I intend to use this template for both structures and classes. How do I do that? Do I have to write template specialization?
Jan 29 2007
"Artyom Shalkhakov" <artyom.sh gmail.ru> wrote in message news:epmlh5$2crr$1 digitaldaemon.com...Okay, I've tried to use pointer to class because I intend to use this template for both structures and classes. How do I do that? Do I have to write template specialization?
Yep. You can do something like: struct temp_t( type : Object ) { void setOwner( type newOwner ) { owner = newOwner; } type getOwner() { return owner; } protected { temp_t * head; temp_t * next; temp_t * prev; type owner; } } struct temp_t( type ) { void setOwner( type *newOwner ) { owner = newOwner; } type *getOwner() { return owner; } protected { temp_t * head; temp_t * next; temp_t * prev; type * owner; } } So it'll use the non-pointer version for classes (i.e. anything that derives from Object), and the pointer version for everything else.
Jan 30 2007
Jarrett Billingsley wrote:"Artyom Shalkhakov" <artyom.sh gmail.ru> wrote in message news:epmlh5$2crr$1 digitaldaemon.com...Okay, I've tried to use pointer to class because I intend to use this template for both structures and classes. How do I do that? Do I have to write template specialization?
Yep. You can do something like: struct temp_t( type : Object ) { void setOwner( type newOwner ) { owner = newOwner; } type getOwner() { return owner; } protected { temp_t * head; temp_t * next; temp_t * prev; type owner; } } struct temp_t( type ) { void setOwner( type *newOwner ) { owner = newOwner; } type *getOwner() { return owner; } protected { temp_t * head; temp_t * next; temp_t * prev; type * owner; } }
static if + is-expressions (and creative 'alias' usage) clean that up pretty well: ----- struct temp_t( type ) { static if(is(type == class)) alias type RefType; else alias type* RefType; void setOwner( RefType newOwner ) { owner = newOwner; } RefType getOwner() { return owner; } protected { temp_t * head; temp_t * next; temp_t * prev; RefType owner; } } ----- Code duplication is ugly.
Jan 30 2007
"Frits van Bommel" <fvbommel REMwOVExCAPSs.nl> wrote in message news:epnmuo$n9t$2 digitaldaemon.com...static if + is-expressions (and creative 'alias' usage) clean that up pretty well: ----- struct temp_t( type ) { static if(is(type == class)) alias type RefType; else alias type* RefType; void setOwner( RefType newOwner ) { owner = newOwner; } RefType getOwner() { return owner; } protected { temp_t * head; temp_t * next; temp_t * prev; RefType owner; } }
Ahh, I was thinking about static if but thought that doing it for each member would have been ugly.. never thought about using an aliased type.
Jan 30 2007








"Jarrett Billingsley" <kb3ctd2 yahoo.com>