Thread overview
consts by another name
Mar 07, 2005
Matthew
Mar 07, 2005
Matthew
Mar 07, 2005
Ben Hinkle
Mar 07, 2005
Matthew
Mar 07, 2005
Ben Hinkle
Mar 07, 2005
Walter
Mar 07, 2005
Matthew
Mar 07, 2005
Walter
Mar 07, 2005
Matthew
Mar 07, 2005
Derek Parnell
March 07, 2005
I know that asking for the full ramifications of const is a never-gonna-happen, but I sorely miss one of the most useful, and relatively simple, applications of this amazingly powerful little keyword in C++: that of guaranteeing initialisation.

My Database class has the following members.

    uint        m_flags;
    size_type   m_numLines;
    Record[]    m_records;
    Field[]     m_fields;

Construction of an instance of Database is a non-trivial (i.e. far from atomic) operation. The processing of a database file involves parsing content into fields and then gathering fields into records.

Since databases may be instantiated from more than one format, factoring out initialisation between multiple constructors increases the likelihood of errors in initialisation of the members.

Since, in C++ (rant, rant, rant), I am used to, and rather good at, having the compiler detect such things for me, I sorely miss this in D.

So, what I'd like is some construct (and maybe 'final' can be it) that gives an error *at compile time* if a variable so marked has not been initialised during any constructor.

Since I'm somewhat rusty, I've just spent some time perusing the docs, but can't find anything pertaining to final. And it's a trivial matter to introduce an uninitialised final member which causes the compiler no consternation.

So, are there any serious objections to this behaviour, through final or another keyword, because this is another area in which D is (currently) manifestly deficient wrt C++?

Matthew



March 07, 2005
ha! I bloody well missed one: m_numLines.

:-(


"Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:d0h8ni$22cc$1@digitaldaemon.com...
>I know that asking for the full ramifications of const is a never-gonna-happen, but I sorely miss one of the most useful, and relatively simple, applications of this amazingly powerful little keyword in C++: that of guaranteeing initialisation.
>
> My Database class has the following members.
>
>    uint        m_flags;
>    size_type   m_numLines;
>    Record[]    m_records;
>    Field[]     m_fields;
>
> Construction of an instance of Database is a non-trivial (i.e. far from atomic) operation. The processing of a database file involves parsing content into fields and then gathering fields into records.
>
> Since databases may be instantiated from more than one format, factoring out initialisation between multiple constructors increases the likelihood of errors in initialisation of the members.
>
> Since, in C++ (rant, rant, rant), I am used to, and rather good at, having the compiler detect such things for me, I sorely miss this in D.
>
> So, what I'd like is some construct (and maybe 'final' can be it) that gives an error *at compile time* if a variable so marked has not been initialised during any constructor.
>
> Since I'm somewhat rusty, I've just spent some time perusing the docs, but can't find anything pertaining to final. And it's a trivial matter to introduce an uninitialised final member which causes the compiler no consternation.
>
> So, are there any serious objections to this behaviour, through final or another keyword, because this is another area in which D is (currently) manifestly deficient wrt C++?
>
> Matthew
>
>
> 


March 07, 2005
"Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:d0h8ni$22cc$1@digitaldaemon.com...
>I know that asking for the full ramifications of const is a never-gonna-happen, but I sorely miss one of the most useful, and relatively simple, applications of this amazingly powerful little keyword in C++: that of guaranteeing initialisation.
>
> My Database class has the following members.
>
>    uint        m_flags;
>    size_type   m_numLines;
>    Record[]    m_records;
>    Field[]     m_fields;
>
> Construction of an instance of Database is a non-trivial (i.e. far from atomic) operation. The processing of a database file involves parsing content into fields and then gathering fields into records.
>
> Since databases may be instantiated from more than one format, factoring out initialisation between multiple constructors increases the likelihood of errors in initialisation of the members.
>
> Since, in C++ (rant, rant, rant), I am used to, and rather good at, having the compiler detect such things for me, I sorely miss this in D.
>
> So, what I'd like is some construct (and maybe 'final' can be it) that gives an error *at compile time* if a variable so marked has not been initialised during any constructor.

Java allows "final" on fields and local variables, which means the variable can only be assigned to once. When I looked up the exact spec http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html#10931 it turns out it also allows "blank final" variables which means there isn't an initializer so it isn't quite the same as what you are proposing. I don't know how well this would work out with D's inout and out parameters but it's worth a shot IMO.


March 07, 2005
"Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:d0h8ni$22cc$1@digitaldaemon.com...
> I know that asking for the full ramifications of const is a
never-gonna-happen, but I sorely miss one of the most
> useful, and relatively simple, applications of this amazingly powerful
little keyword in C++: that of guaranteeing
> initialisation.
>
> My Database class has the following members.
>
>     uint        m_flags;
>     size_type   m_numLines;
>     Record[]    m_records;
>     Field[]     m_fields;
>
> Construction of an instance of Database is a non-trivial (i.e. far from
atomic) operation. The processing of a database
> file involves parsing content into fields and then gathering fields into
records.
>
> Since databases may be instantiated from more than one format, factoring
out initialisation between multiple
> constructors increases the likelihood of errors in initialisation of the
members.

The way to deal with that is to use "forwarding constructors", a feature proposed for C++ but not implemented. It's implemented in D. D will also provide a default initializer, or a user specified default initializer, guaranteeing that all members are initialized, instead of the C++ way of leaving such things undefined.

> Since, in C++ (rant, rant, rant), I am used to, and rather good at, having
the compiler detect such things for me, I
> sorely miss this in D.

That would only be for const members in C++. Non const C++ members get no detection at all, not at compile time, not at runtime. The members just contain uninitialized garbage.

> So, what I'd like is some construct (and maybe 'final' can be it) that
gives an error *at compile time* if a variable so
> marked has not been initialised during any constructor.
> Since I'm somewhat rusty, I've just spent some time perusing the docs, but
can't find anything pertaining to final. And
> it's a trivial matter to introduce an uninitialised final member which
causes the compiler no consternation.
>
> So, are there any serious objections to this behaviour, through final or
another keyword, because this is another area
> in which D is (currently) manifestly deficient wrt C++?

I see your point about wanting the compiler to give an error on uninitialized members, but in D, members are not uninitialized. C++ only gives such errors for const members. For non const members, C++ gives no help at all. And I understand that you've said you've rarely had a problem with this, but I have, and it's a nasty deficiency in C++. I guess I just am not understanding why not initializing const members is a manifest deficiency, while not initializing non-const members is not much of an issue.


March 07, 2005
Here's another way you can use forwarding constructors. Given:

class C
{
    int a, b, c;
}

create a constructor:

    this(int a, int b, int c) { this.a = a; this.b = b; this.c = c; }

Then, for your multitude of constructor needs, forward the actual member initialization to the above this():

    this(MyParameter p)
    {
            ...
            this(exp1, exp2, exp3);
    }

Then, if you add a member d:

    int a, b, c, d;

and add it to the forwarding constructor:

    this(int a, int b, int c, int d) { this.a = a; this.b = b; this.c = c;
this.d = d; }

then any constructors that are not so updated will cause an error.


March 07, 2005
"Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:d0hur9$2peg$1@digitaldaemon.com...
>
> "Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:d0h8ni$22cc$1@digitaldaemon.com...
>>I know that asking for the full ramifications of const is a never-gonna-happen, but I sorely miss one of the most useful, and relatively simple, applications of this amazingly powerful little keyword in C++: that of guaranteeing initialisation.
>>
>> My Database class has the following members.
>>
>>    uint        m_flags;
>>    size_type   m_numLines;
>>    Record[]    m_records;
>>    Field[]     m_fields;
>>
>> Construction of an instance of Database is a non-trivial (i.e. far from atomic) operation. The processing of a database file involves parsing content into fields and then gathering fields into records.
>>
>> Since databases may be instantiated from more than one format, factoring out initialisation between multiple constructors increases the likelihood of errors in initialisation of the members.
>>
>> Since, in C++ (rant, rant, rant), I am used to, and rather good at, having the compiler detect such things for me, I sorely miss this in D.
>>
>> So, what I'd like is some construct (and maybe 'final' can be it) that gives an error *at compile time* if a variable so marked has not been initialised during any constructor.
>
> Java allows "final" on fields and local variables, which means the variable can only be assigned to once. When I looked up the exact spec http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html#10931 it turns out it also allows "blank final" variables which means there isn't an initializer so it isn't quite the same as what you are proposing.

Damn. Well I always say Java's a stinking pile of crap ...

> I don't know how well this would work out with D's inout and out parameters but it's worth a shot IMO.

I only care - at the moment at least - about the compiler guaranteeing at runtime that a variable is explicitly initialised. I cannot imagine that this is terribly hard - although a compiler writer I'm not.




March 07, 2005
"Walter" <newshound@digitalmars.com> wrote in message news:d0i8qe$3ml$1@digitaldaemon.com...
>
> "Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:d0h8ni$22cc$1@digitaldaemon.com...
>> I know that asking for the full ramifications of const is a
> never-gonna-happen, but I sorely miss one of the most
>> useful, and relatively simple, applications of this amazingly powerful
> little keyword in C++: that of guaranteeing
>> initialisation.
>>
>> My Database class has the following members.
>>
>>     uint        m_flags;
>>     size_type   m_numLines;
>>     Record[]    m_records;
>>     Field[]     m_fields;
>>
>> Construction of an instance of Database is a non-trivial (i.e. far from
> atomic) operation. The processing of a database
>> file involves parsing content into fields and then gathering fields into
> records.
>>
>> Since databases may be instantiated from more than one format, factoring
> out initialisation between multiple
>> constructors increases the likelihood of errors in initialisation of the
> members.
>
> The way to deal with that is to use "forwarding constructors", a feature proposed for C++ but not implemented.

Off the point entirely.

> It's implemented in D. D will also
> provide a default initializer, or a user specified default initializer,
> guaranteeing that all members are initialized, instead of the C++ way of
> leaving such things undefined.

Yeah. And therefore it won't warn about an uninitialised variable.

Score yet another win for C++ over D!

:-(

>
>> Since, in C++ (rant, rant, rant), I am used to, and rather good at, having
> the compiler detect such things for me, I
>> sorely miss this in D.
>
> That would only be for const members in C++. Non const C++ members get no detection at all, not at compile time, not at runtime. The members just contain uninitialized garbage.

True. But not the point, since I'm asking for a keyword that can be applied at the programmer's discretion, not a general behaviour for all member variables.

>> So, what I'd like is some construct (and maybe 'final' can be it) that
> gives an error *at compile time* if a variable so
>> marked has not been initialised during any constructor.
>> Since I'm somewhat rusty, I've just spent some time perusing the docs, but
> can't find anything pertaining to final. And
>> it's a trivial matter to introduce an uninitialised final member which
> causes the compiler no consternation.
>>
>> So, are there any serious objections to this behaviour, through final or
> another keyword, because this is another area
>> in which D is (currently) manifestly deficient wrt C++?
>
> I see your point about wanting the compiler to give an error on uninitialized members, but in D, members are not uninitialized.

Oh come on! I'm nearly 37, .and I've lost nearly a centimetre of hairline in the last five years. You're gonna have me tearing out all the rest if you carry on like this.

Yes, I know I said uninitialised, but you know I meant "not explicitly initialised". Sigh

> C++ only
> gives such errors for const members.

Oh really?
    References?
    Members of class type with non-default constructors?

> For non const members, C++ gives no
> help at all.

True. But C++ compilers do!!!!

> And I understand that you've said you've rarely had a problem with this, but I have, and it's a nasty deficiency in C++.

So, if some proportion of the community have, and some proportion haven't, is the answer to arbitrarily side with one, or to cater for both?

> I guess I just am
> not understanding why not initializing const members is a manifest
> deficiency, while not initializing non-const members is not much of an
> issue.

Well, in one sense, you don't have to understand, do you? The DMC++ compiler provides const, yet you don't understand the many excellent uses for this feature.

But this particular facet of C++ const - and I'm only arguing for *this particular facet* going into D - is that I could mark my class member variables as, say, 'explicit', and the compiler would then issue an error if any of them are not explicitly initialised in all constructors.

The rationale? See my second post on this thread, beginning with "ha!". My first non-trivial class in months has just such an error in it.

You may never forget to explicitly initialise member variables in non-trivial classes, but we mortals do. Unless and until you can show that this small subset of const's behaviour would result in unacceptable compiler complexity and/or programmer confusion, I suggest its absence is a flaw.





March 07, 2005
"Walter" <newshound@digitalmars.com> wrote in message news:d0ibp9$6sf$1@digitaldaemon.com...
> Here's another way you can use forwarding constructors. Given:
>
> class C
> {
>    int a, b, c;
> }
>
> create a constructor:
>
>    this(int a, int b, int c) { this.a = a; this.b = b; this.c = c; }
>
> Then, for your multitude of constructor needs, forward the actual member initialization to the above this():
>
>    this(MyParameter p)
>    {
>            ...
>            this(exp1, exp2, exp3);
>    }
>
> Then, if you add a member d:
>
>    int a, b, c, d;
>
> and add it to the forwarding constructor:
>
>    this(int a, int b, int c, int d) { this.a = a; this.b = b; this.c = c;
> this.d = d; }
>
> then any constructors that are not so updated will cause an error.

Sure. I worked all this out in a heartbeat. I also worked out an even nicer (IMO) option using a static private method that takes out params.

But this is all entirely off the point of my requirement for (what I'm now calling) 'explicit'.





March 07, 2005
On Tue, 8 Mar 2005 07:59:28 +1100, Matthew wrote:

> "Walter" <newshound@digitalmars.com> wrote in message news:d0ibp9$6sf$1@digitaldaemon.com...
>> Here's another way you can use forwarding constructors. Given:
>>
>> class C
>> {
>>    int a, b, c;
>> }
>>
>> create a constructor:
>>
>>    this(int a, int b, int c) { this.a = a; this.b = b; this.c = c; }
>>
>> Then, for your multitude of constructor needs, forward the actual member initialization to the above this():
>>
>>    this(MyParameter p)
>>    {
>>            ...
>>            this(exp1, exp2, exp3);
>>    }
>>
>> Then, if you add a member d:
>>
>>    int a, b, c, d;
>>
>> and add it to the forwarding constructor:
>>
>>    this(int a, int b, int c, int d) { this.a = a; this.b = b; this.c = c;
>> this.d = d; }
>>
>> then any constructors that are not so updated will cause an error.
> 
> Sure. I worked all this out in a heartbeat. I also worked out an even nicer (IMO) option using a static private method that takes out params.
> 
> But this is all entirely off the point of my requirement for (what I'm now calling) 'explicit'.

Matthew, can I summarize your request thus ...

Would it possible to have some mechanism (eg. a new keyword) that designates specific class members as 'must have explicit initialization', and thus have the compiler produce a error message for all such members that have no explicit initialization in any of the class' constructor functions.

-- 
Derek
Melbourne, Australia
8/03/2005 9:46:04 AM
March 07, 2005
In article <d0iea8$a20$1@digitaldaemon.com>, Matthew says...
>
>
>"Ben Hinkle" <bhinkle@mathworks.com> wrote in message news:d0hur9$2peg$1@digitaldaemon.com...
>>
>> "Matthew" <admin.hat@stlsoft.dot.org> wrote in message news:d0h8ni$22cc$1@digitaldaemon.com...
>>>I know that asking for the full ramifications of const is a never-gonna-happen, but I sorely miss one of the most useful, and relatively simple, applications of this amazingly powerful little keyword in C++: that of guaranteeing initialisation.
>>>
>>> My Database class has the following members.
>>>
>>>    uint        m_flags;
>>>    size_type   m_numLines;
>>>    Record[]    m_records;
>>>    Field[]     m_fields;
>>>
>>> Construction of an instance of Database is a non-trivial (i.e. far from atomic) operation. The processing of a database file involves parsing content into fields and then gathering fields into records.
>>>
>>> Since databases may be instantiated from more than one format, factoring out initialisation between multiple constructors increases the likelihood of errors in initialisation of the members.
>>>
>>> Since, in C++ (rant, rant, rant), I am used to, and rather good at, having the compiler detect such things for me, I sorely miss this in D.
>>>
>>> So, what I'd like is some construct (and maybe 'final' can be it) that gives an error *at compile time* if a variable so marked has not been initialised during any constructor.
>>
>> Java allows "final" on fields and local variables, which means the variable can only be assigned to once. When I looked up the exact spec http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html#10931 it turns out it also allows "blank final" variables which means there isn't an initializer so it isn't quite the same as what you are proposing.
>
>Damn. Well I always say Java's a stinking pile of crap ...

hmm - no wonder you're so grumpy about D. IMO D shares more in common with Java/C# than with C++.

>> I don't know how well this would work out with D's inout and out parameters but it's worth a shot IMO.
>
>I only care - at the moment at least - about the compiler guaranteeing at runtime that a variable is explicitly initialised. I cannot imagine that this is terribly hard - although a compiler writer I'm not.

Agreed - and it sounds like Walter will get to it eventually.