D - Bug: constructor calls
- Hauke Duden <H.NS.Duden gmx.net> Jan 06 2004
- "Walter" <walter digitalmars.com> Jan 10 2004
- Hauke Duden <H.NS.Duden gmx.net> Jan 10 2004
- "Walter" <walter digitalmars.com> Jan 17 2004
- Hauke Duden <H.NS.Duden gmx.net> Jan 18 2004
- Vathix <vathix dprogramming.com> Jan 18 2004
- Andy Friesen <andy ikagames.com> Jan 17 2004
- Hauke Duden <H.NS.Duden gmx.net> Jan 18 2004
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...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.
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. Hauke
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...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.
I hereby make a motion to introduce the keyword "shaddap", that makes the compiler stop complaining about these kinds of warnings-turned-errors ;). Hauke
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 ;). Hauke
There'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. Hauke
Foo2 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:This works: [...] Why is the constructor in Foo1 acceptable, while the one in Foo2 is not? I believe this is a bug. Hauke
Foo2 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.
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. Hauke
Jan 18 2004









Vathix <vathix dprogramming.com> 