D - Bug: constructor calls
- Hauke Duden (39/39) Jan 06 2004 This works:
- Walter (6/40) Jan 10 2004 Actually, it is designed to work that way. The semantic phase does a rat...
- Hauke Duden (16/70) Jan 10 2004 So how can I circumvent this? In my real world example I don't want to
- Walter (5/19) Jan 17 2004 It's an interesting tradeoff, adding in the dummy constructor in one cas...
- Hauke Duden (5/30) Jan 18 2004 I hereby make a motion to introduce the keyword "shaddap", that makes
- Vathix (2/8) Jan 18 2004 There's a switch for this, that big button on your computer case :>
- Andy Friesen (29/36) Jan 17 2004 Foo2 shouldn't have to (shouldn't be *able* to!) rely on the internal
- Hauke Duden (11/26) Jan 18 2004 While this may be true in many cases, it is not in this particular case....
This works: class Foo1 { this(bool b) { if(b) val=14; } this() { val=7; } protected: int val; } This doesn't (Error: one path skips constructor: class Foo2 { this(bool b) { if(b) val=14; else this(); //<< crucial line } this() { val=7; } protected: int val; } Why is the constructor in Foo1 acceptable, while the one in Foo2 is not? I believe this is a bug. Hauke
Jan 06 2004
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:btf4jn$1irs$1 digitaldaemon.com...This works: class Foo1 { this(bool b) { if(b) val=14; } this() { val=7; } protected: int val; } This doesn't (Error: one path skips constructor: class Foo2 { this(bool b) { if(b) val=14; else this(); //<< crucial line } this() { val=7; } protected: int val; } Why is the constructor in Foo1 acceptable, while the one in Foo2 is not? I believe this is a bug.Actually, it is designed to work that way. The semantic phase does a rather primitive data flow analysis to determine that if another constructor is called on one path through the constructor, it must be called on all paths through.
Jan 10 2004
Walter wrote:"Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:btf4jn$1irs$1 digitaldaemon.com...So how can I circumvent this? In my real world example I don't want to call the default constructor because that would cause a lot of unnecessary stuff to happen (like allocating memory that is thrown away right afterwards). Do I have to write a empty bogus constructor overload with an invented list of parameters that I can call from the first code path? That would be SUCH a hack... This is one of the things you always wanted to prevent in D. I know this code is right and I just want the compiler to shut up :(. And it is also very similar to requiring returns in all code paths. Why do you allow missing returns, but you don't allow missing constructor calls? At least in the return case it is easy to "make the compiler shut up". In the constructor case I don't even know how, except for that ugly invented empty constructor hack. HaukeThis works: class Foo1 { this(bool b) { if(b) val=14; } this() { val=7; } protected: int val; } This doesn't (Error: one path skips constructor: class Foo2 { this(bool b) { if(b) val=14; else this(); //<< crucial line } this() { val=7; } protected: int val; } Why is the constructor in Foo1 acceptable, while the one in Foo2 is not? I believe this is a bug.Actually, it is designed to work that way. The semantic phase does a rather primitive data flow analysis to determine that if another constructor is called on one path through the constructor, it must be called on all paths through.
Jan 10 2004
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:btota8$1ijf$1 digitaldaemon.com...So how can I circumvent this? In my real world example I don't want to call the default constructor because that would cause a lot of unnecessary stuff to happen (like allocating memory that is thrown away right afterwards). Do I have to write a empty bogus constructor overload with an invented list of parameters that I can call from the first code path? That would be SUCH a hack... This is one of the things you always wanted to prevent in D. I know this code is right and I just want the compiler to shut up :(. And it is also very similar to requiring returns in all code paths. Why do you allow missing returns, but you don't allow missing constructor calls? At least in the return case it is easy to "make the compiler shut up". In the constructor case I don't even know how, except for that ugly invented empty constructor hack.It's an interesting tradeoff, adding in the dummy constructor in one case, and leaving in a potential large source of inadvertent bugs. I think the thing to do is wait and see how things evolve a bit.
Jan 17 2004
Walter wrote:"Hauke Duden" <H.NS.Duden gmx.net> wrote in message news:btota8$1ijf$1 digitaldaemon.com...I hereby make a motion to introduce the keyword "shaddap", that makes the compiler stop complaining about these kinds of warnings-turned-errors ;). HaukeSo how can I circumvent this? In my real world example I don't want to call the default constructor because that would cause a lot of unnecessary stuff to happen (like allocating memory that is thrown away right afterwards). Do I have to write a empty bogus constructor overload with an invented list of parameters that I can call from the first code path? That would be SUCH a hack... This is one of the things you always wanted to prevent in D. I know this code is right and I just want the compiler to shut up :(. And it is also very similar to requiring returns in all code paths. Why do you allow missing returns, but you don't allow missing constructor calls? At least in the return case it is easy to "make the compiler shut up". In the constructor case I don't even know how, except for that ugly invented empty constructor hack.It's an interesting tradeoff, adding in the dummy constructor in one case, and leaving in a potential large source of inadvertent bugs. I think the thing to do is wait and see how things evolve a bit.
Jan 18 2004
Hauke Duden wrote:I hereby make a motion to introduce the keyword "shaddap", that makes the compiler stop complaining about these kinds of warnings-turned-errors ;). HaukeThere's a switch for this, that big button on your computer case :>
Jan 18 2004
Hauke Duden wrote:This works: [...] Why is the constructor in Foo1 acceptable, while the one in Foo2 is not? I believe this is a bug. HaukeFoo2 shouldn't have to (shouldn't be *able* to!) rely on the internal representation of Foo1. What you're doing is very dangerous from a design or maintenance perspective. I'm almost ready to say that it should be an error if each of Foo2's constructors do not call exactly one Foo1 constructor. What you should do is something more like: class Foo1 { // uber-paranoid. Use the accessor even internally. this(int v) { val = v; } this() { this(0); } int val() { return _val; } void val(int v) { _val = v; } private: // not protected int _val; } class Foo2 { this(bool b) { if (b) super(); else super(17); } } Of course, this is all effectively religious dogma, but I'd say it's a very good thing if Foo2 is completely incapable of breaking because of changes to Foo1's implementation. -- andy
Jan 17 2004
Andy Friesen wrote:Hauke Duden wrote:While this may be true in many cases, it is not in this particular case. The base class actually does not have a constructor, because it is a completely abstract class. It doesn't even have any member variables, it is only there to provide default implementations for some interface functions. This kind of implementation helper for an interface is often a very big help. Besides: the problem was not that I called a base class constructor - I called another constructor of the same class in one code branch and didn't in another. HaukeThis works: [...] Why is the constructor in Foo1 acceptable, while the one in Foo2 is not? I believe this is a bug. HaukeFoo2 shouldn't have to (shouldn't be *able* to!) rely on the internal representation of Foo1. What you're doing is very dangerous from a design or maintenance perspective.
Jan 18 2004