www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - consts by another name

reply "Matthew" <admin.hat stlsoft.dot.org> writes:
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
Mar 07 2005
next sibling parent "Matthew" <admin.hat stlsoft.dot.org> writes:
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


 

Mar 07 2005
prev sibling next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"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/typesV lues.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.
Mar 07 2005
parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
"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/typesV lues.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.
Mar 07 2005
parent Ben Hinkle <Ben_member pathlink.com> writes:
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/typesV lues.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.
Mar 07 2005
prev sibling next sibling parent reply "Walter" <newshound digitalmars.com> writes:
"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

 useful, and relatively simple, applications of this amazingly powerful

 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

 file involves parsing content into fields and then gathering fields into

 Since databases may be instantiated from more than one format, factoring

 constructors increases the likelihood of errors in initialisation of the

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

 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

 marked has not been initialised during any constructor.
 Since I'm somewhat rusty, I've just spent some time perusing the docs, but

 it's a trivial matter to introduce an uninitialised final member which

 So, are there any serious objections to this behaviour, through final or

 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.
Mar 07 2005
parent "Matthew" <admin.hat stlsoft.dot.org> writes:
"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

 useful, and relatively simple, applications of this amazingly powerful

 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

 file involves parsing content into fields and then gathering fields into

 Since databases may be instantiated from more than one format, factoring

 constructors increases the likelihood of errors in initialisation of the

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

 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

 marked has not been initialised during any constructor.
 Since I'm somewhat rusty, I've just spent some time perusing the docs, but

 it's a trivial matter to introduce an uninitialised final member which

 So, are there any serious objections to this behaviour, through final or

 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.
Mar 07 2005
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
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.
Mar 07 2005
parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
"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'.
Mar 07 2005
parent Derek Parnell <derek psych.ward> writes:
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
Mar 07 2005