initialization of a const static float data member in a class

Discussion in 'C++' started by akomiakov@gmail.com, Jun 12, 2008.

  1. Guest

    Is there a technical reason why one can't initialize a cost static non-
    integral data member in a class?
    , Jun 12, 2008
    #1
    1. Advertising

  2. wrote:
    > Is there a technical reason why one can't initialize a cost static non-
    > integral data member in a class?


    Probably not.

    Moreover, it should probably be seen the other way around. The bottom
    line here is that in C++ normally non-defining declarations can't
    include initializers. An exception was made for integral and enum types
    only. And the real question here is whether there's a reason for this
    exception. The answer is: yes, there is. The exception was made for
    constants of integral and enum types in order to allow these constants
    to participate in integral constant expressions. For other types there
    is no good reason to allow the initialization.

    --
    Best regards,
    Andrey Tarasevich
    Andrey Tarasevich, Jun 12, 2008
    #2
    1. Advertising

  3. Guest

    On Jun 13, 12:05 am, Andrey Tarasevich <>
    wrote:
    > wrote:
    > > Is there a technical reason why one can't initialize a cost static non-
    > > integral data member in a class?

    >
    > Probably not.
    >
    > Moreover, it should probably be seen the other way around. The bottom
    > line here is that in C++ normally non-defining declarations can't
    > include initializers. An exception was made for integral and enum types
    > only. And the real question here is whether there's a reason for this
    > exception. The answer is: yes, there is. The exception was made for
    > constants of integral and enum types in order to allow these constants
    > to participate in integral constant expressions. For other types there
    > is no good reason to allow the initialization.
    >
    > --
    > Best regards,
    > Andrey Tarasevich


    Thanks a lot.
    , Jun 13, 2008
    #3
  4. James Kanze Guest

    On Jun 12, 10:16 pm, "Alf P. Steinbach" <> wrote:
    > * Andrey Tarasevich:


    > > The exception was made for
    > > constants of integral and enum types in order to allow these constants
    > > to participate in integral constant expressions.


    > Yes.


    > > For other types there
    > > is no good reason to allow the initialization.


    > Sorry, but that statement is in blatant contradiction of fact.


    Yes and no. There is no imperative language based reason to
    allow them. Of course, this is at least partially linked to the
    fact templates can't have floating point parameters, but the
    fact remains that at present, there's nothing at the language
    level which you can do with a floating point constant whose
    initialization can be seen that you can't also do with one whose
    initialization can't be seen.

    I'm just curious, but do you have any examples where being able
    to define the initialization in the class definition (which is
    definitely a hack) would make some coding simpler. The main
    argument I know in favor of it is orthogonality---it's allowed
    for integral types, and there doesn't seem to be any really good
    reason for not allowing it for floating point. (Given that the
    hack is already present, applying it to a few more types doesn't
    seem to make a significant difference in the "hackness".)

    For that matter, is there any persuasive reason for not allowing
    the initialization in the class definition for all static data
    members. Obviously, in cases where it implied dynamic
    initialization, it would be ignored except where the variable
    was actually defined, but if you're going to have a hack, you
    might as well be systematic about it.

    > The fact is, this functionality is requested again and again
    > and again,


    By whom? I don't recall having seen any such request (but there
    was a long period in which I wasn't that active in
    standardization, so I easily could have missed it).

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orient�e objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34
    James Kanze, Jun 13, 2008
    #4
  5. James Kanze Guest

    On Jun 13, 6:10 pm, "Alf P. Steinbach" <> wrote:
    > * James Kanze:
    > > On Jun 12, 10:16 pm, "Alf P. Steinbach" <> wrote:
    > >> * Andrey Tarasevich:


    > >>> The exception was made for
    > >>> constants of integral and enum types in order to allow these constants
    > >>> to participate in integral constant expressions.


    > >> Yes.


    > >>> For other types there
    > >>> is no good reason to allow the initialization.


    > >> Sorry, but that statement is in blatant contradiction of fact.


    > > Yes and no. There is no imperative language based reason to
    > > allow them. Of course, this is at least partially linked to the
    > > fact templates can't have floating point parameters, but the
    > > fact remains that at present, there's nothing at the language
    > > level which you can do with a floating point constant whose
    > > initialization can be seen that you can't also do with one whose
    > > initialization can't be seen.


    > I'm sorry but that argument doesn't hold water.


    For you. For most of the members of the committee (and for all
    of the other experts I know), it does. The general feeling is
    that ideally, you shouldn't be able to provide the
    initialization in the class definition at all---it's an ugly
    hack. But there are language imperatives for allowing it for
    integral types. (My own opinion is that you either have the
    hack, or you don't. Extending it to double, or even all other
    types, doesn't seem a problem to me once you've got the hack.
    But I don't decide these things anymore than you do.)

    > > I'm just curious, but do you have any examples where being
    > > able to define the initialization in the class definition
    > > (which is definitely a hack) would make some coding simpler.


    > I can't see any example where it wouldn't?


    > Assuming a practical language rule, of course, where the
    > current sillyness of having to define the identifier
    > separately (outside the class definition) if it's "used", is
    > dropped.


    OK. That's a major change in the way C++ works. Or at least in
    the way it worked before templates. In other words, what you
    want is for the declaration of a static class member to be a
    definition, and drop the one definition rule on it.

    I'm not sure I agree, but it's certainly something worth
    considering.

    > Note in that respect: using templating trick all the required
    > code is in header file, and within current language rules, so
    > there's no reason that the compiler can't do that rewrite
    > automatically, and check for errors, and so requirement of
    > separate definition if "used" is just silly, completely
    > redundant.


    Oh, I don't have any doubt that its implementable. It would
    have caused problems 15 years ago, but as you say, it can just
    piggyback on techniques needed for templates anyway.

    > [snip]


    > >> The fact is, this functionality is requested again and
    > >> again and again,


    > > By whom? I don't recall having seen any such request (but
    > > there was a long period in which I wasn't that active in
    > > standardization, so I easily could have missed it).


    > I don't know about requests to the standards committee,


    Those are the only ones which will actually get acted upon.

    > except I know it has been discussed. I think that historically
    > (discussing the last year or so would be absurd, nothing new
    > is going to make it into C++0x),


    I don't know about that. One of the proposals I made in the
    last year or so has been accepted (that <iostream> be required
    to include <istream> and <ostream>). Admittedly, however, it
    was just a request to bring the standard in line with existing
    practice.

    > with the understanding that there were at least a few
    > committee members very much against doing the right thing,
    > nobody would take the trouble of wasting time by making a
    > formal proposal. Speculating haphazardly, I conjecture that
    > any proposal that would make some prominent committee members
    > feel that they'd been made to look like fools,


    Times change, and many committee members accept today things
    they would have rejected in the past. You obviously have to
    present it in a polite fashion: it might have been the right
    thing in the past, but technology has evolved. (In 1991, when I
    started using C++ professionally, implementing your suggestion
    of not requiring the additional definition would have been
    almost impossible.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jun 13, 2008
    #5
  6. Kai-Uwe Bux Guest

    James Kanze wrote:

    > On Jun 13, 6:10 pm, "Alf P. Steinbach" <> wrote:
    >> * James Kanze:
    >> > On Jun 12, 10:16 pm, "Alf P. Steinbach" <> wrote:
    >> >> * Andrey Tarasevich:

    >
    >> >>> The exception was made for
    >> >>> constants of integral and enum types in order to allow these
    >> >>> constants to participate in integral constant expressions.

    >
    >> >> Yes.

    >
    >> >>> For other types there
    >> >>> is no good reason to allow the initialization.

    >
    >> >> Sorry, but that statement is in blatant contradiction of fact.

    >
    >> > Yes and no. There is no imperative language based reason to
    >> > allow them. Of course, this is at least partially linked to the
    >> > fact templates can't have floating point parameters, but the
    >> > fact remains that at present, there's nothing at the language
    >> > level which you can do with a floating point constant whose
    >> > initialization can be seen that you can't also do with one whose
    >> > initialization can't be seen.

    >
    >> I'm sorry but that argument doesn't hold water.

    >
    > For you. For most of the members of the committee (and for all
    > of the other experts I know), it does. The general feeling is
    > that ideally, you shouldn't be able to provide the
    > initialization in the class definition at all---it's an ugly
    > hack.

    [snip]

    Actually, I wonder where that assesment comes from. In my coding style (I do
    almost exclusively templated code), all code goes into header files. I
    rarely ever split declarations from definitions. Being forced to do that
    for static const members creates an imbalance in coding style that makes
    the non-hack ugly and the hack natural.

    I don't think it is a good idea for the standard to legislate style; and for
    templated code, the issue is more or less entirely a matter of style.


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Jun 13, 2008
    #6
  7. Ian Collins Guest

    Alf P. Steinbach wrote:
    > * James Kanze:
    >
    >> I'm just curious, but do you have any examples where being able
    >> to define the initialization in the class definition (which is
    >> definitely a hack) would make some coding simpler.

    >
    > I can't see any example where it wouldn't?
    >

    One argument I've heard is differences between the compilation host and
    target floating point representations. 42 is always 42, but
    0.123*12345.678 may not have the same representation on all hardware.

    --
    Ian Collins.
    Ian Collins, Jun 13, 2008
    #7
  8. Greg Herlihy Guest

    On Jun 13, 10:07 am, Kai-Uwe Bux <> wrote:
    > > For you.  For most of the members of the committee (and for all
    > > of the other experts I know), it does.  The general feeling is
    > > that ideally, you shouldn't be able to provide the
    > > initialization in the class definition at all---it's an ugly
    > > hack.

    >
    > [snip]
    >
    > Actually, I wonder where that assesment comes from. In my coding style (I do
    > almost exclusively templated code), all code goes into header files. I
    > rarely ever split declarations from definitions. Being forced to do that
    > for static const members creates an imbalance in coding style that makes
    > the non-hack ugly and the hack natural.
    >
    > I don't think it is a good idea for the standard to legislate style; and for
    > templated code, the issue is more or less entirely a matter of style.


    C++09 will allow the in-definition intialization of any static class
    member of a "literal" type - including floating point types. After
    all, it probably doesn't make much sense to most C++ programmers, that
    a floating point constant in a header file is OK outside of a class
    definition - but suddenly becomes a problem when moved inside a class
    definition:

    // header.h

    const float kFloatConstant = 1.0f; // OK

    class A
    {
    public:
    static float kFloatConstant = 2.0f; // Error - but OK in C++09
    };

    Greg
    Greg Herlihy, Jun 14, 2008
    #8
  9. Greg Herlihy Guest

    On Jun 13, 10:07 am, Kai-Uwe Bux <> wrote:
    > James Kanze wrote:.
    >
    > > For you.  For most of the members of the committee (and for all
    > > of the other experts I know), it does.  The general feeling is
    > > that ideally, you shouldn't be able to provide the
    > > initialization in the class definition at all---it's an ugly
    > > hack.

    >
    > [snip]
    >
    > Actually, I wonder where that assesment comes from. In my coding style (I do
    > almost exclusively templated code), all code goes into header files. I
    > rarely ever split declarations from definitions. Being forced to do that
    > for static const members creates an imbalance in coding style that makes
    > the non-hack ugly and the hack natural.
    >
    > I don't think it is a good idea for the standard to legislate style; and for
    > templated code, the issue is more or less entirely a matter of style.


    C++09 will allow the in-definition initialization of any static class
    member of a "literal" type - including floating point types. After
    all, it probably does not make much sense to most C++ programmers that
    a constant floating point variable may be declared in a header file
    (outside of a class) - but may not be declared in a header file
    (inside of a class):

    // header.h

    const float kFloatConstant = 1.0f; // OK

    class A
    {
    public:
    static const float kFloatConstant = 2.0f; // Error - but OK in C+
    +09
    }

    Greg
    Greg Herlihy, Jun 14, 2008
    #9
  10. Ian Collins Guest

    Alf P. Steinbach wrote:
    > * Ian Collins:
    >> Alf P. Steinbach wrote:
    >>> * James Kanze:
    >>>
    >>>> I'm just curious, but do you have any examples where being able
    >>>> to define the initialization in the class definition (which is
    >>>> definitely a hack) would make some coding simpler.
    >>> I can't see any example where it wouldn't?
    >>>

    >> One argument I've heard is differences between the compilation host and
    >> target floating point representations. 42 is always 42, but
    >> 0.123*12345.678 may not have the same representation on all hardware.

    >
    > It's just a specious red herring argument.
    >

    One case would be a cross-compiler.

    > After all, there's nothing preventing us from defining these constants
    > with the current language.
    >

    That's true, but I don't think they are classed as compile time
    constants (not that is makes much difference for a floating point value)
    where as an integer type is.

    A quick check with Sun CC shows "const float ff = 42.0*42.0;" is
    calculated at run time with all but the most relaxed architecture and
    floating point compiler options.

    > It's just that with current rules it's a load of unnecessary notation
    > and complication and no guaranteed checking that you've fulfilled the
    > language's requirements.
    >
    > Now I see else-thread that purportedly C++0x will fix this.
    >

    There is a case for consistency.

    > If so, hurray (I haven't noticed that, but then I haven't scrutinized
    > the draft!) -- and if so, it sort of pulls the rug under James'
    > argument that
    >
    > "For most of the members of the committee (and for all of the other
    > experts I know), [There is no imperative language based reason to allow
    > [these in-class definition initializations]]. The general feeling is
    > that ideally, you shouldn't be able to provide the initialization in the
    > class definition at all"
    >

    :)

    A always thought the exception for integer types was to remove the
    necessity for the old enum hack compile time constant (for an array size
    for instance). This was a pain in pre-standard compilers, just as it is
    in C today.

    It looks like the exception is about to become the rule!

    --
    Ian Collins.
    Ian Collins, Jun 14, 2008
    #10
  11. James Kanze Guest

    On Jun 13, 7:07 pm, Kai-Uwe Bux <> wrote:
    > James Kanze wrote:
    > > On Jun 13, 6:10 pm, "Alf P. Steinbach" <> wrote:
    > >> * James Kanze:
    > >> > On Jun 12, 10:16 pm, "Alf P. Steinbach" <> wrote:
    > >> >> * Andrey Tarasevich:


    > >> >>> The exception was made for constants of integral and
    > >> >>> enum types in order to allow these constants to
    > >> >>> participate in integral constant expressions.


    > >> >> Yes.


    > >> >>> For other types there is no good reason to allow the
    > >> >>> initialization.


    > >> >> Sorry, but that statement is in blatant contradiction of fact.


    > >> > Yes and no. There is no imperative language based reason to
    > >> > allow them. Of course, this is at least partially linked to the
    > >> > fact templates can't have floating point parameters, but the
    > >> > fact remains that at present, there's nothing at the language
    > >> > level which you can do with a floating point constant whose
    > >> > initialization can be seen that you can't also do with one whose
    > >> > initialization can't be seen.


    > >> I'm sorry but that argument doesn't hold water.


    > > For you. For most of the members of the committee (and for all
    > > of the other experts I know), it does. The general feeling is
    > > that ideally, you shouldn't be able to provide the
    > > initialization in the class definition at all---it's an ugly
    > > hack.


    > [snip]
    >
    > Actually, I wonder where that assesment comes from.


    Well, I heard it from people very close to Stroustrup; they gave
    the impression that it was from him:).

    The actual point, of course, is that according to the standard,
    the declaration of a static data member is *not* a definition.
    There are also very good reasons for this, or at least, there
    were twenty years ago, when the decision was made. And of
    course, you can't provide an initializer in a declaration that
    is not a definition.

    That's the C++ object model, and allowing the initialiser for
    integral types (but only if it is a constant) is a hack with
    regards to that.

    For the moment, I don't know exactly what the counter-proposal
    is, so it's hard to argue against it, or agree with it. If the
    proposal is that the declaration in the class should be a
    definition (and thus, that you don't need a definition
    elsewhere), then I'm radically against it; such a rule would
    mean that things like:
    static int someArray[] ;
    would be illegal (since a definition requires a complete type),
    and that you'd always have to provide the initializer in the
    class (and most of the time, you really don't want to).

    I can understand Alf's desire that all types (and not just
    integral types) can have an initializer, and that shouldn't be
    too hard to specify nor to implement. With regards to his
    desire that you not need the separate definition, however, I'd
    want to see the actual proposal. I understand the desire, but I
    fear that it would require significant rework of the meaning of
    definitions and declarations, which in turn is very likely to
    have effects elsewhere.

    > In my coding style (I do almost exclusively templated code),
    > all code goes into header files. I rarely ever split
    > declarations from definitions.


    I'm not sure I understand, and I don't quite see what templates
    have to do with it. Whether the definition is in the header
    file (or a file included from the header file) or in some
    separate source file doesn't really change much.

    > Being forced to do that for static const members creates an
    > imbalance in coding style that makes the non-hack ugly and the
    > hack natural.


    > I don't think it is a good idea for the standard to legislate
    > style; and for templated code, the issue is more or less
    > entirely a matter of style.


    I'm afraid I don't see where templates change anything. But
    whatever. Until there is a concrete proposal, I don't know what
    I'm considering.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jun 14, 2008
    #11
  12. James Kanze Guest

    On Jun 14, 1:14 am, Greg Herlihy <> wrote:
    > On Jun 13, 10:07 am, Kai-Uwe Bux <> wrote:
    > > James Kanze wrote:.


    > > > For you. For most of the members of the committee (and
    > > > for all of the other experts I know), it does. The
    > > > general feeling is that ideally, you shouldn't be able to
    > > > provide the initialization in the class definition at
    > > > all---it's an ugly hack.


    > > [snip]


    > > Actually, I wonder where that assesment comes from. In my
    > > coding style (I do almost exclusively templated code), all
    > > code goes into header files. I rarely ever split
    > > declarations from definitions. Being forced to do that for
    > > static const members creates an imbalance in coding style
    > > that makes the non-hack ugly and the hack natural.


    > > I don't think it is a good idea for the standard to
    > > legislate style; and for templated code, the issue is more
    > > or less entirely a matter of style.


    > C++09 will allow the in-definition initialization of any
    > static class member of a "literal" type - including floating
    > point types. After all, it probably does not make much sense
    > to most C++ programmers that a constant floating point
    > variable may be declared in a header file (outside of a class)
    > - but may not be declared in a header file (inside of a
    > class):


    > // header.h


    > const float kFloatConstant = 1.0f; // OK


    > class A
    > {
    > public:
    > static const float kFloatConstant = 2.0f; // Error - but OK in C+
    > +09
    > }


    There's one very big difference between the two: every source
    which includes the header has a separate instance of
    ::kFloatConstant, but there is only one instance of
    ::A::kFloatConstant in the entire program. And of course, the
    fact that you still have to define A::kFloatConstant somewhere.

    In many ways, the correct analogy would be:

    extern float const kFloatConstant ;
    // declaration, not definition

    class A
    {
    public:
    static float const kFloatConstant ;
    // declaration, not definition
    } ;

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jun 14, 2008
    #12
  13. James Kanze Guest

    On Jun 14, 4:30 am, "Alf P. Steinbach" <> wrote:
    > * Ian Collins:


    > > Alf P. Steinbach wrote:
    > >> * James Kanze:


    > >>> I'm just curious, but do you have any examples where being
    > >>> able to define the initialization in the class definition
    > >>> (which is definitely a hack) would make some coding
    > >>> simpler.
    > >> I can't see any example where it wouldn't?


    > > One argument I've heard is differences between the
    > > compilation host and target floating point representations.
    > > 42 is always 42, but 0.123*12345.678 may not have the same
    > > representation on all hardware.


    > It's just a specious red herring argument.


    Historically, it wasn't. And it wasn't a question of
    representation, but actual value: 5*7 is equal to 35 always,
    everywhere. The actual value of 1.2*3.4 depends on the floating
    point representation, however.

    Note that this very definitely was the motivation for not
    allowing floating point arguments for templates. Given
    something like:
    template< double F > class T{} ;
    do
    T< 1.2*3.4 > t1 ;
    T< 4.08 > t2 ;
    have the same type or not?

    Of course, this argument doesn't really apply to the initializer
    of a static member. But historically, C has made a point of not
    requiring a cross compiler to implement the target floating
    point arithmetic---there is currently no where in the language
    where the compiler is required to do floating point arithmetic.

    > After all, there's nothing preventing us from defining these
    > constants with the current language.


    The language currently does not have the concept of a constant
    0.123*12345.678.

    > It's just that with current rules it's a load of unnecessary
    > notation and complication and no guaranteed checking that
    > you've fulfilled the language's requirements.


    Which current rule? That you have to define the variable if you
    use it? G++ certainly gives an error here, even if the variable
    has an initializer. (Technically, of course, it is the linker
    that gives the error, but error there is.)

    > Now I see else-thread that purportedly C++0x will fix this.


    Fix what? I have the impression that we are talking about
    several different things here. I don't have the very latest
    draft here, but from what I can see, all that has changed is
    that you can now provide an initializer for any "const literal
    type" (whatever that is---I'm guessing that it means a type for
    which some literal exists). You still have to provide a
    definition somewhere.

    To date, as I said, I'm not aware of any proposal to change
    this. And I don't feel competent to discuss the pros and cons
    of a proposal that doesn't exist---I want to know exactly what
    is being proposed, first.

    > If so, hurray (I haven't noticed that, but then I haven't
    > scrutinized the draft!) -- and if so, it sort of pulls the
    > rug under James' argument that


    > "For most of the members of the committee (and for all of the
    > other experts I know), [There is no imperative language based
    > reason to allow [these in-class definition initializations]].
    > The general feeling is that ideally, you shouldn't be able to
    > provide the initialization in the class definition at all"


    You'll have to explain that one to me. There is no imperative
    language based reason. Once you have the hack, there's a good
    argument (orthogonality) for extending it to all types. And of
    course, *ideally*, we wouldn't need the hack (but as we all
    know, C++ is based more on pragmatics than on ideals). (But to
    be honest, I should have qualified the "most". I've not really
    spoken to that many on the subject, so the "most" really only
    applies to a small sampling.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jun 14, 2008
    #13
  14. James Kanze Guest

    On Jun 14, 4:50 am, Ian Collins <> wrote:

    [...]
    > A always thought the exception for integer types was to remove
    > the necessity for the old enum hack compile time constant (for
    > an array size for instance). This was a pain in pre-standard
    > compilers, just as it is in C today.


    That was the original motivation.

    > It looks like the exception is about to become the rule!


    I suspect (but I've not actually talked to the people involved)
    that the motivation for extending it to "literal types" is
    orthogonality. While allowing it for anything is certainly a
    bit of a hack, allowing it for int and not for double seems
    rather arbitrary too.

    For the rest, it's still a hack: the declaration in the class
    itself is still not a definition, and you still have to provide
    a definition elsewhere. (And presumably, compilers will still
    complain if you use the variable and don't provide a
    declaration---with a possible exception if the use involves an
    immediate lvalue to rvalue conversion of an integral type.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jun 14, 2008
    #14
  15. Ian Collins Guest

    James Kanze wrote:
    >
    > For the rest, it's still a hack: the declaration in the class
    > itself is still not a definition, and you still have to provide
    > a definition elsewhere. (And presumably, compilers will still
    > complain if you use the variable and don't provide a
    > declaration---with a possible exception if the use involves an
    > immediate lvalue to rvalue conversion of an integral type.)
    >

    Interesting point. With current compilers, a declaration is only
    required if the address of a static const member is used. Presumably
    the value is a compile time constant, so the declaration is not required
    in immediate uses.

    With a floating point type, this will not be the case. So which rules
    will apply in the new standard? If a declaration is required for all
    uses, plenty of existing code will break.

    --
    Ian Collins.
    Ian Collins, Jun 14, 2008
    #15
  16. Kai-Uwe Bux Guest

    James Kanze wrote:

    > On Jun 13, 7:07 pm, Kai-Uwe Bux <> wrote:
    >> James Kanze wrote:
    >> > On Jun 13, 6:10 pm, "Alf P. Steinbach" <> wrote:
    >> >> * James Kanze:
    >> >> > On Jun 12, 10:16 pm, "Alf P. Steinbach" <> wrote:
    >> >> >> * Andrey Tarasevich:

    >
    >> >> >>> The exception was made for constants of integral and
    >> >> >>> enum types in order to allow these constants to
    >> >> >>> participate in integral constant expressions.

    >
    >> >> >> Yes.

    >
    >> >> >>> For other types there is no good reason to allow the
    >> >> >>> initialization.

    >
    >> >> >> Sorry, but that statement is in blatant contradiction of fact.

    >
    >> >> > Yes and no. There is no imperative language based reason to
    >> >> > allow them. Of course, this is at least partially linked to the
    >> >> > fact templates can't have floating point parameters, but the
    >> >> > fact remains that at present, there's nothing at the language
    >> >> > level which you can do with a floating point constant whose
    >> >> > initialization can be seen that you can't also do with one whose
    >> >> > initialization can't be seen.

    >
    >> >> I'm sorry but that argument doesn't hold water.

    >
    >> > For you. For most of the members of the committee (and for all
    >> > of the other experts I know), it does. The general feeling is
    >> > that ideally, you shouldn't be able to provide the
    >> > initialization in the class definition at all---it's an ugly
    >> > hack.

    >
    >> [snip]
    >>
    >> Actually, I wonder where that assesment comes from.

    >
    > Well, I heard it from people very close to Stroustrup; they gave
    > the impression that it was from him:).
    >
    > The actual point, of course, is that according to the standard,
    > the declaration of a static data member is *not* a definition.
    > There are also very good reasons for this, or at least, there
    > were twenty years ago, when the decision was made. And of
    > course, you can't provide an initializer in a declaration that
    > is not a definition.
    >
    > That's the C++ object model, and allowing the initialiser for
    > integral types (but only if it is a constant) is a hack with
    > regards to that.
    >
    > For the moment, I don't know exactly what the counter-proposal
    > is, so it's hard to argue against it, or agree with it. If the
    > proposal is that the declaration in the class should be a
    > definition (and thus, that you don't need a definition
    > elsewhere), then I'm radically against it; such a rule would
    > mean that things like:
    > static int someArray[] ;
    > would be illegal (since a definition requires a complete type),
    > and that you'd always have to provide the initializer in the
    > class (and most of the time, you really don't want to).


    So let's try to reword [9.4.2/2]:

    The declaration of a static data member in its class definition is not a
    definition and may be of an incomplete type other than cv-qualified void
    unless it specifies an initializer, in which case it is a definition and
    the type shall be complete. If the declaration is not a definition, the
    definition for a static data member shall appear in a namespace scope
    enclosing the member?s class definition. In the definition at namespace
    scope, the name of the static data member shall be qualified by its class
    name using the :: operator. The initializer expression in the definition
    of a static data member is in the scope of its class (3.3.6).

    What about that?


    > I can understand Alf's desire that all types (and not just
    > integral types) can have an initializer, and that shouldn't be
    > too hard to specify nor to implement. With regards to his
    > desire that you not need the separate definition, however, I'd
    > want to see the actual proposal. I understand the desire, but I
    > fear that it would require significant rework of the meaning of
    > definitions and declarations, which in turn is very likely to
    > have effects elsewhere.
    >
    >> In my coding style (I do almost exclusively templated code),
    >> all code goes into header files. I rarely ever split
    >> declarations from definitions.

    >
    > I'm not sure I understand, and I don't quite see what templates
    > have to do with it. Whether the definition is in the header
    > file (or a file included from the header file) or in some
    > separate source file doesn't really change much.


    I think, you misunderstood what I meant by splitting declarations and
    definitions. I usually write

    template < typename T >
    class some_class {


    void some_method ( some_type some_arg ) {
    // implementation
    }

    };

    instead of

    template < typename T >
    class some_class {


    some_result_type some_method ( some_type some_arg );

    };

    template < typename T >
    some_class<T>::some_result_type
    some_class<T>::some_method ( some_class<T>::some_type some_arg ) {
    // implementation
    }


    >> Being forced to do that for static const members creates an
    >> imbalance in coding style that makes the non-hack ugly and the
    >> hack natural.

    >
    >> I don't think it is a good idea for the standard to legislate
    >> style; and for templated code, the issue is more or less
    >> entirely a matter of style.

    >
    > I'm afraid I don't see where templates change anything.


    They don't change the technical side of things. However, as you can see
    above, the separation of the definition from the declaration becomes quite
    wordy for templates. Moreover, it has very little return for the effort
    since compilers by and large do not support export and the main technical
    reasons to hide definitions do not apply. That influences coding style.

    > But
    > whatever. Until there is a concrete proposal, I don't know what
    > I'm considering.


    See above.


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Jun 14, 2008
    #16
  17. Greg Herlihy Guest

    On Jun 14, 3:46 pm, Kai-Uwe Bux <> wrote:
    > James Kanze wrote:
    > > For the moment, I don't know exactly what the counter-proposal
    > > is, so it's hard to argue against it, or agree with it.  If the
    > > proposal is that the declaration in the class should be a
    > > definition (and thus, that you don't need a definition
    > > elsewhere), then I'm radically against it; such a rule would
    > > mean that things like:
    > >     static int someArray[] ;
    > > would be illegal (since a definition requires a complete type),
    > > and that you'd always have to provide the initializer in the
    > > class (and most of the time, you really don't want to).

    >
    > So let's try to reword [9.4.2/2]:
    >
    >   The declaration of a static data member in its class definition is not a
    >   definition and may be of an incomplete type other than cv-qualified void
    >   unless it specifies an initializer, in which case it is a definition and
    >   the type shall be complete. If the declaration is not a definition, the
    >   definition for a static data member shall appear in a namespace scope
    >   enclosing the member?s class definition. In the definition at namespace
    >   scope, the name of the static data member shall be qualified by its class
    >   name using the :: operator. The initializer expression in the definition
    >   of a static data member is in the scope of its class (3.3.6).
    >
    > What about that?


    Actually, I think the next paragraph is the more interesting one:

    "If a static data member is of const literal type, its declaration in
    the class definition can specify a constant-initializer. A static data
    member of literal type can be declared in the class definition with
    the constexpr specifier; if so, its declaration shall specify a
    constant-initializer. In both these cases, the member may appear in
    integral constant expressions. The member shall still be deï¬ned in a
    namespace scope if it is used in the program and the namespace scope
    deï¬nition shall not contain an initializer."[§9.4/3 N2606]

    The Draft also defines a "literal" type:

    A type is a literal type if it is:

    — a scalar type;

    or

    — a class type (clause 9) with
    — a trivial copy constructor,
    — a trivial destructor,
    — at least one constexpr constructor
    other than the copy constructor,
    — no virtual base classes,
    and
    — all non-static data members and base classes
    of literal types;
    or

    — an array of literal type. [§3.9/10 N2606]

    So there seem to be two ways in C++09 to provide an in-class
    initializer for a const static class member: either declare the const
    static member with a constexpr specifier, or (the more old-fashioned
    way) with a simple "static const" specifier.

    Note that when the class member is defined with a constexpr specifier,
    no corresponding member definition outside of the class may appear.
    Even in the "const" case, an out-of-class definition is needed only if
    the member is "used" in the program (which essentially means - only if
    its address is taken). Otherwise, the declaration and "initialization"
    of the const static member inside of the class definition - is enough.

    Greg
    Greg Herlihy, Jun 15, 2008
    #17
  18. Greg Herlihy Guest

    On Jun 14, 3:41 pm, Ian Collins <> wrote:
    > James Kanze wrote:
    >
    > > For the rest, it's still a hack: the declaration in the class
    > > itself is still not a definition, and you still have to provide
    > > a definition elsewhere.  (And presumably, compilers will still
    > > complain if you use the variable and don't provide a
    > > declaration---with a possible exception if the use involves an
    > > immediate lvalue to rvalue conversion of an integral type.)

    >
    > Interesting point.  With current compilers, a declaration is only
    > required if the address of a static const member is used.  Presumably
    > the value is a compile time constant, so the declaration is not required
    > in immediate uses.
    >
    > With a floating point type, this will not be the case.  So which rules
    > will apply in the new standard?  If a declaration is required for all
    > uses, plenty of existing code will break.


    No, the innitialization of static const floating point class members
    will not be treated any differently than the way that in-class
    initialization of static const integral class members is handled in
    the current Standard. Essentially, no out-of-class definition will be
    needed for a const static class member (of a literal type) that has
    been initialized within a class declaration. Unless, of course, the
    program "uses" that class member.

    According to the Draft, a variable is "used" if:

    An object or non-overloaded function whose name appears as a
    potentially-evaluated expression is "used" unless it is an object that
    satisfies the requirements for appearing in a constant expression
    (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately
    applied.[§3.2/2 N2606]

    Note that C99 has supported constant floating point expressions for
    over eight years now, so in some ways, C++ is simply catching up.

    Greg
    Greg Herlihy, Jun 15, 2008
    #18
  19. Ian Collins Guest

    Greg Herlihy wrote:
    > On Jun 14, 3:41 pm, Ian Collins <> wrote:
    >> James Kanze wrote:
    >>
    >>> For the rest, it's still a hack: the declaration in the class
    >>> itself is still not a definition, and you still have to provide
    >>> a definition elsewhere. (And presumably, compilers will still
    >>> complain if you use the variable and don't provide a
    >>> declaration---with a possible exception if the use involves an
    >>> immediate lvalue to rvalue conversion of an integral type.)

    >> Interesting point. With current compilers, a declaration is only
    >> required if the address of a static const member is used. Presumably
    >> the value is a compile time constant, so the declaration is not required
    >> in immediate uses.
    >>
    >> With a floating point type, this will not be the case. So which rules
    >> will apply in the new standard? If a declaration is required for all
    >> uses, plenty of existing code will break.

    >
    > No, the innitialization of static const floating point class members
    > will not be treated any differently than the way that in-class
    > initialization of static const integral class members is handled in
    > the current Standard. Essentially, no out-of-class definition will be
    > needed for a const static class member (of a literal type) that has
    > been initialized within a class declaration. Unless, of course, the
    > program "uses" that class member.
    >
    > According to the Draft, a variable is "used" if:
    >
    > An object or non-overloaded function whose name appears as a
    > potentially-evaluated expression is "used" unless it is an object that
    > satisfies the requirements for appearing in a constant expression
    > (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately
    > applied.[§3.2/2 N2606]
    >

    OK, thanks.

    > Note that C99 has supported constant floating point expressions for
    > over eight years now, so in some ways, C++ is simply catching up.
    >

    So has C++, just not for class members.

    --
    Ian Collins.
    Ian Collins, Jun 15, 2008
    #19
  20. James Kanze Guest

    On Jun 15, 12:46 am, Kai-Uwe Bux <> wrote:
    > James Kanze wrote:


    [...]
    > > For the moment, I don't know exactly what the
    > > counter-proposal is, so it's hard to argue against it, or
    > > agree with it. If the proposal is that the declaration in
    > > the class should be a definition (and thus, that you don't
    > > need a definition elsewhere), then I'm radically against it;
    > > such a rule would mean that things like:
    > > static int someArray[] ;
    > > would be illegal (since a definition requires a complete
    > > type), and that you'd always have to provide the initializer
    > > in the class (and most of the time, you really don't want
    > > to).


    > So let's try to reword [9.4.2/2]:


    > The declaration of a static data member in its class
    > definition is not a definition and may be of an incomplete
    > type other than cv-qualified void unless it specifies an
    > initializer, in which case it is a definition and the type
    > shall be complete. If the declaration is not a definition,
    > the definition for a static data member shall appear in a
    > namespace scope enclosing the member?s class definition. In
    > the definition at namespace scope, the name of the static
    > data member shall be qualified by its class name using the
    > :: operator. The initializer expression in the definition of
    > a static data member is in the scope of its class (3.3.6).


    > What about that?


    It's a start. Of course, you'll also need something in §3.2.
    Otherwise, a header which contains something like:

    struct S { static int i = 43 ; } ;

    will cause undefined behavior if it is included in more than one
    translation unit.

    Also, consider the issues of backwards compatibility; your
    suggestion would make a lot of currently conforming code
    illegal (since the previously required definition would suddenly
    become a duplicate definition).

    But those problems should be solvable as well. The real problem
    is, of course, that on one has presented such a proposition to
    the committee (and I suspect that it is too late now---we should
    be very, very close to a CD, if the next version is really to be
    C++0x, and not C++1x).

    > > I can understand Alf's desire that all types (and not just
    > > integral types) can have an initializer, and that shouldn't be
    > > too hard to specify nor to implement. With regards to his
    > > desire that you not need the separate definition, however, I'd
    > > want to see the actual proposal. I understand the desire, but I
    > > fear that it would require significant rework of the meaning of
    > > definitions and declarations, which in turn is very likely to
    > > have effects elsewhere.


    > >> In my coding style (I do almost exclusively templated code),
    > >> all code goes into header files. I rarely ever split
    > >> declarations from definitions.


    > > I'm not sure I understand, and I don't quite see what templates
    > > have to do with it. Whether the definition is in the header
    > > file (or a file included from the header file) or in some
    > > separate source file doesn't really change much.


    > I think, you misunderstood what I meant by splitting declarations and
    > definitions. I usually write


    > template < typename T >
    > class some_class {
    > void some_method ( some_type some_arg ) {
    > // implementation
    > }
    > };


    > instead of


    > template < typename T >
    > class some_class {
    > some_result_type some_method ( some_type some_arg );
    > };


    > template < typename T >
    > some_class<T>::some_result_type
    > some_class<T>::some_method ( some_class<T>::some_type some_arg ) {
    > // implementation
    > }


    You mean that you make almost all of your functions inline?

    In my work, it is normal to insist that the implementations be
    in a separate file (even if, in the case of templates, this file
    is included by the header). It's more or less a basic principle
    if you're working in large systems (or more strictly speaking,
    if there are more than two or three people working on the
    application); you don't want the interface to accidentally
    change after some bug fix in the implementation. (If you've
    never accidentally changed something you didn't mean to, you're
    a better typist than I am. Where as it's impossible to
    accidentally change something in a file you haven't checked
    out.)

    > >> Being forced to do that for static const members creates an
    > >> imbalance in coding style that makes the non-hack ugly and the
    > >> hack natural.


    > >> I don't think it is a good idea for the standard to legislate
    > >> style; and for templated code, the issue is more or less
    > >> entirely a matter of style.


    > > I'm afraid I don't see where templates change anything.


    > They don't change the technical side of things. However, as
    > you can see above, the separation of the definition from the
    > declaration becomes quite wordy for templates.


    There's a fair amount of redundance even for non-templates:). A
    good editor helps, but there's still a fair bit of typing to do.

    > Moreover, it has very little return for the effort since
    > compilers by and large do not support export and the main
    > technical reasons to hide definitions do not apply. That
    > influences coding style.


    Even without export, I use separate files. For one, it will
    make migration to a compiler which supports export simpler, and
    for the other, it still keeps the implementation in a separate
    file from the interface---essential when you have more than a
    few people working on the same code base (but I agree that
    without export, templates are pretty much unusable at the
    application level).

    > > But whatever. Until there is a concrete proposal, I don't
    > > know what I'm considering.


    > See above.


    Next step: get it to the committee. If you'd like, write it up
    in the format of a formal proposal (with motivation, impact, and
    potentially discussion of other alteratives, and why they are
    rejected), and send it to me by private email, and I'll take
    charge of presenting it. But don't get your hopes up too
    much---two or three years ago, I think it would have found a
    good deal of interest, but I fear that it's a bit too late at
    present. (On the other hand, it's possible that something else
    will come up which delays the standard, and someone on the
    committee might take advantage of that to slip it through.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Jun 15, 2008
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. bd
    Replies:
    0
    Views:
    604
  2. Spoon
    Replies:
    7
    Views:
    407
    John Carson
    Dec 31, 2006
  3. Javier
    Replies:
    2
    Views:
    542
    James Kanze
    Sep 4, 2007
  4. fungus
    Replies:
    13
    Views:
    871
    fungus
    Oct 31, 2008
  5. Carsten Fuchs
    Replies:
    45
    Views:
    1,504
    James Kanze
    Oct 8, 2009
Loading...

Share This Page