digitalmars.D.learn - Weird (?) problem
- mike (79/79) Aug 09 2006 Hi!
- Ary Manzana (20/100) Aug 10 2006 Have you tried placing code after "instance = new TypeType()"?
- mike (33/52) Aug 10 2006 Thanks, it works! :-)
- Ary Manzana (6/70) Aug 10 2006 Watch out!! Unit tests are only for debug purposes, once you compile
- James Dunne (36/68) Aug 10 2006 Create two constructors for your TypeType classes.
Hi!
I've run into a big problem in my project, it's not really a problem wit=
h =
D, more a problem with ... you'll see.
Anyway: I've got a couple of classes in my project which represent type =
=
information (like MIDI notes, audio output, sample data, etc. - it'll be=
=
an audio app written in D). Basically it's a reflection system with some=
=
extras that are specific to this project.
Now, the idea is that every of these type classes has a static field whi=
ch =
holds a single instance, like that:
' class TypeFoo : TypeBase
' {
' static TypeBase instance =3D null;
' static this() { instance =3D new TypeFoo(); }
' }
I've got a static opCall to return that instance:
' static TypeBase opCall() { return instance; }
Now everywhere I need to call an overloaded constructor or tell some =
object which type of other objects it can process, I just can call
' TypeFoo()
and get my type class.
Next is, I've got a namespace- or registry-like tree system, where all =
objects are stored into. That's where I store the information of "I can =
=
process objects of type X" too. It's somehow like:
' getObject("foo").setType(TypeFoo());
' getObject("foo").addCanProcess(TypeBar());
Now the thing is that the type classes need to identify themselves to th=
e =
rest of the system as type classes. Therefore I've got a TypeType class.=
=
Which also resides in that tree.
Up until now I set up this information on my type classes via a =
"construct"-function, which was called at a point where the class =
instances already exist. But I'm a bit fed up of having to maintain two =
=
pieces of code (class definition and the construct-function), so I decid=
ed =
to make the type classes able to set up themselves. And here the trouble=
=
starts.
So: In the TypeType static c'tor, I make a new instance of that class. =
Then the normal c'tor is called, trying to setup itself in the tree =
system, telling everybody that it is indead a type. So ... it needs the =
=
very instance of the TypeType class that is being constructed at that ve=
ry =
moment ... so: access violation.
' class TypeType : TypeBase
' {
' TypeBase instance =3D null;
' static this() { instance =3D new TypeType(); }
' static TypeBase opCall() { return instance; }
' this()
' {
' addObject("typetype");
' getObject("typetype").setType(TypeType()); // crashes: access=
=
violation
' }
' }
It's a bit of a chicken and egg problem. I can't new an instance of that=
=
class unless there's already one instance there. Is it possible to solve=
=
that somehow? Something like an "after_this()" or the like? I guess I've=
=
outsmarted myself there and I have no idea what to do about it besides =
reverting to the old system with that stupid, ugly construct function =
(shudder).
Any ideas would be really appreciated.
-Mike
-- =
Erstellt mit Operas revolution=E4rem E-Mail-Modul: http://www.opera.com/=
mail/
Aug 09 2006
mike wrote:
Hi!
I've run into a big problem in my project, it's not really a problem
with D, more a problem with ... you'll see.
Anyway: I've got a couple of classes in my project which represent type
information (like MIDI notes, audio output, sample data, etc. - it'll be
an audio app written in D). Basically it's a reflection system with some
extras that are specific to this project.
Now, the idea is that every of these type classes has a static field
which holds a single instance, like that:
' class TypeFoo : TypeBase
' {
' static TypeBase instance = null;
' static this() { instance = new TypeFoo(); }
' }
I've got a static opCall to return that instance:
' static TypeBase opCall() { return instance; }
Now everywhere I need to call an overloaded constructor or tell some
object which type of other objects it can process, I just can call
' TypeFoo()
and get my type class.
Next is, I've got a namespace- or registry-like tree system, where all
objects are stored into. That's where I store the information of "I can
process objects of type X" too. It's somehow like:
' getObject("foo").setType(TypeFoo());
' getObject("foo").addCanProcess(TypeBar());
Now the thing is that the type classes need to identify themselves to
the rest of the system as type classes. Therefore I've got a TypeType
class. Which also resides in that tree.
Up until now I set up this information on my type classes via a
"construct"-function, which was called at a point where the class
instances already exist. But I'm a bit fed up of having to maintain two
pieces of code (class definition and the construct-function), so I
decided to make the type classes able to set up themselves. And here the
trouble starts.
So: In the TypeType static c'tor, I make a new instance of that class.
Then the normal c'tor is called, trying to setup itself in the tree
system, telling everybody that it is indead a type. So ... it needs the
very instance of the TypeType class that is being constructed at that
very moment ... so: access violation.
' class TypeType : TypeBase
' {
' TypeBase instance = null;
' static this() { instance = new TypeType(); }
' static TypeBase opCall() { return instance; }
' this()
' {
' addObject("typetype");
' getObject("typetype").setType(TypeType()); // crashes: access
violation
' }
' }
It's a bit of a chicken and egg problem. I can't new an instance of that
class unless there's already one instance there. Is it possible to solve
that somehow? Something like an "after_this()" or the like? I guess I've
outsmarted myself there and I have no idea what to do about it besides
reverting to the old system with that stupid, ugly construct function
(shudder).
Any ideas would be really appreciated.
-Mike
--Erstellt mit Operas revolutionärem E-Mail-Modul:
http://www.opera.com/mail/
Have you tried placing code after "instance = new TypeType()"?
Like this:
' class TypeType : TypeBase
' {
' TypeBase instance = null;
' static this() {
' instance = new TypeType();
' // I don't know whether addObject is a function
' // or a member of TypeType, but you get the point
' instance.addObject("typetype");
' instance.getObject("typetype").setType(instance);
' }
' static TypeBase opCall() { return instance; }
' this()
' {
' }
' }
Hope that helps (and works).
Ary
Aug 10 2006
Thanks, it works! :-)
I still need one little workaround, but that's ok.
Funny thing is: Thinking about it a little bit more I got that idea:
' class TypeFoo : TypeBase
' {
' public:
' static this() { instance =3D new Bar(); }
'
' private:
' void setup() { /* add object, setup */ }
' TypeBase instance;
'
' unittest
' {
' instance.setup();
' }
' }
since the unittest will be executed after ALL static this()'s are done, =
=
and it's the only piece of code that is tied to a class and called =
automatically (besides the constructors) - but I don't want to be that =
evil :-)
Another question:
Is there a way to prevent a derived class from calling super()? I solved=
=
this currently with an empty this(int) and calling super(0), but is ther=
e =
another way?
-Mike
Am 10.08.2006, 14:14 Uhr, schrieb Ary Manzana <asterite gmail.com>:
Have you tried placing code after "instance =3D new TypeType()"?
Like this:
' class TypeType : TypeBase
' {
' TypeBase instance =3D null;
' static this() {
' instance =3D new TypeType();
' // I don't know whether addObject is a function
' // or a member of TypeType, but you get the point
' instance.addObject("typetype");
' instance.getObject("typetype").setType(instance);
' }
' static TypeBase opCall() { return instance; }
' this()
' {
' }
' }
Hope that helps (and works).
Ary
-- =
Erstellt mit Operas revolution=E4rem E-Mail-Modul: http://www.opera.com/=
mail/
Aug 10 2006
mike wrote:Thanks, it works! :-) I still need one little workaround, but that's ok. Funny thing is: Thinking about it a little bit more I got that idea: ' class TypeFoo : TypeBase ' { ' public: ' static this() { instance = new Bar(); } ' ' private: ' void setup() { /* add object, setup */ } ' TypeBase instance; ' ' unittest ' { ' instance.setup(); ' } ' } since the unittest will be executed after ALL static this()'s are done, and it's the only piece of code that is tied to a class and called automatically (besides the constructors) - but I don't want to be that evil :-)Watch out!! Unit tests are only for debug purposes, once you compile your code with the "release" flag, no unit test will ever be invoked.Another question: Is there a way to prevent a derived class from calling super()? I solved this currently with an empty this(int) and calling super(0), but is there another way?I believe not, and it's because of the OOP philosophy... But you can always make a protected constructor for your derived classes, although this increases code dependency between classes, and I don't recommend it.-Mike Am 10.08.2006, 14:14 Uhr, schrieb Ary Manzana <asterite gmail.com>:Have you tried placing code after "instance = new TypeType()"? Like this: ' class TypeType : TypeBase ' { ' TypeBase instance = null; ' static this() { ' instance = new TypeType(); ' // I don't know whether addObject is a function ' // or a member of TypeType, but you get the point ' instance.addObject("typetype"); ' instance.getObject("typetype").setType(instance); ' } ' static TypeBase opCall() { return instance; } ' this() ' { ' } ' } Hope that helps (and works). Ary--Erstellt mit Operas revolutionärem E-Mail-Modul: http://www.opera.com/mail/
Aug 10 2006
mike wrote:
[snip]
So: In the TypeType static c'tor, I make a new instance of that class.
Then the normal c'tor is called, trying to setup itself in the tree
system, telling everybody that it is indead a type. So ... it needs the
very instance of the TypeType class that is being constructed at that
very moment ... so: access violation.
' class TypeType : TypeBase
' {
' TypeBase instance = null;
' static this() { instance = new TypeType(); }
' static TypeBase opCall() { return instance; }
' this()
' {
' addObject("typetype");
' getObject("typetype").setType(TypeType()); // crashes:
access violation
' }
' }
It's a bit of a chicken and egg problem. I can't new an instance of
that class unless there's already one instance there. Is it possible to
solve that somehow? Something like an "after_this()" or the like? I
guess I've outsmarted myself there and I have no idea what to do about
it besides reverting to the old system with that stupid, ugly construct
function (shudder).
Any ideas would be really appreciated.
-Mike
Create two constructors for your TypeType classes.
One private c'tor with a dummy parameter to differentiate it from the
normal public c'tor.
Call that private c'tor in your static c'tor; the private c'tor should
obviously _not_ call into your registration system.
The normal public c'tor should call the registration system, just like
in your code above.
class TypeType : TypeBase {
TypeBase instance = null;
static this() {
instance = new TypeType(true);
addObject("typetype");
addObject("typetype").setType(instance);
}
static TypeBase opCall() { return instance; }
public this() {
addObject("typetype");
getObject("typetype").setType(TypeType());
}
private this(bool dummy) {
// Just a dummy to suppress infinite recursion in constructor
// calls...
}
}
I'm curious as to the purpose of the multiple registration of the
"typetype" named instance in your registry system. I hope you get the
basic idea of what I'm proposing so you can fix these issues yourself. :)
--
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/MU/S d-pu s:+ a-->? C++++$ UL+++ P--- L+++ !E W-- N++ o? K? w--- O
M-- V? PS PE Y+ PGP- t+ 5 X+ !R tv-->!tv b- DI++(+) D++ G e++>e
h>--->++ r+++ y+++
------END GEEK CODE BLOCK------
James Dunne
Aug 10 2006









Ary Manzana <asterite gmail.com> 