member initialization list priority

Discussion in 'C++' started by Dwight Army of Champions, Aug 17, 2010.

  1. can i use already-initialized data members further on when
    initializing other members of the member initialization list?
     
    Dwight Army of Champions, Aug 17, 2010
    #1
    1. Advertising

  2. Dwight Army of Champions

    Öö Tiib Guest

    On 17 aug, 17:18, Dwight Army of Champions
    <> wrote:
    > can i use already-initialized data members further on when
    > initializing other members of the member initialization list?


    No. Order in member initialization list does not affect actual order
    of initialization. Actual order is first virtual bases, then bases,
    then data members in same order like in class declaration.
     
    Öö Tiib, Aug 17, 2010
    #2
    1. Advertising

  3. Dwight Army of Champions <>, on
    17/08/2010 07:18:34, wrote:

    > can i use already-initialized data members further on when
    > initializing other members of the member initialization list?


    The order of execution of the initializers follows the order of
    declaration of the various members, as others pointed out.

    If the initialization list follows a different order, then the compiler
    could issue some warnings, and surely the people reading your code could
    get confused.

    In any case yes, you can use the already initialized values in the other
    initializations:


    #include <iostream>

    using namespace std;

    class Init {
    public:
    Init() : // processing order:
    c(b+1), // last
    b(a+1), // second
    a(1) // first
    {} // bad style as it could confuse the reader
    void print() const {
    cout << "a == " << a << endl;
    cout << "b == " << b << endl;
    cout << "c == " << c << endl;
    }
    private:
    // in the initialization list the order will be
    int a; // first initialization
    int b; // second initialization
    int c; // third initialization
    // regardless of the initialization order
    };

    int main() {
    Init i;
    i.print();
    }





    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
     
    Francesco S. Carta, Aug 17, 2010
    #3
  4. Dwight Army of Champions

    Öö Tiib Guest

    On 17 aug, 17:45, "Leigh Johnston" <> wrote:
    > "Öö Tiib" <> wrote in message
    >
    > news:...
    >
    > > On 17 aug, 17:18, Dwight Army of Champions
    > > <> wrote:
    > >> can i use already-initialized data members further on when
    > >> initializing other members of the member initialization list?

    >
    > > No. Order in member initialization list does not affect actual order
    > > of initialization. Actual order is first virtual bases, then bases,
    > > then data members in same order like in class declaration.

    >
    > Yes but .. "Order in member initialization list does not affect actual order
    > of initialization. Actual order is first virtual bases, then bases,
    > then data members in same order like in class declaration."
    >
    > :)


    Yes, that is also not wrong. ;) Some policies demand both orders to be
    same, despite compilers do not care. It removes the yes/no situation
    about the whole topic.
     
    Öö Tiib, Aug 17, 2010
    #4
  5. Dwight Army of Champions

    Jorgen Grahn Guest

    On Tue, 2010-08-17, Öö Tiib wrote:
    > On 17 aug, 17:18, Dwight Army of Champions
    > <> wrote:
    >> can i use already-initialized data members further on when
    >> initializing other members of the member initialization list?

    >
    > No. Order in member initialization list does not affect actual order
    > of initialization. Actual order is first virtual bases, then bases,
    > then data members in same order like in class declaration.


    But your answer "no" does not follow from your explanation.

    I cannot say "yes" for sure, but I often do what the original poster
    asks for. My compiler (g++) warns me if my initializations aren't in
    declaration order, so I feel I can safely do it.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
     
    Jorgen Grahn, Aug 17, 2010
    #5
  6. Dwight Army of Champions wrote:
    > can i use already-initialized data members further on when
    > initializing other members of the member initialization list?


    Yes, but keep in mind that order of initialization is the same as order
    of member declaration in the class definition.

    The members that are "already initialized" by the moment you get to
    member M are the members that are declared before M in the class
    definition.

    The order in which you mention the members in the constructor
    initializer list does not matter.

    --
    Best regards,
    Andrey Tarasevich
     
    Andrey Tarasevich, Aug 17, 2010
    #6
  7. Dwight Army of Champions

    Öö Tiib Guest

    On 17 aug, 20:02, Jorgen Grahn <> wrote:
    > On Tue, 2010-08-17, Öö Tiib wrote:
    > > On 17 aug, 17:18, Dwight Army of Champions
    > > <> wrote:
    > >> can i use already-initialized data members further on when
    > >> initializing other members of the member initialization list?

    >
    > > No. Order in member initialization list does not affect actual order
    > > of initialization. Actual order is first virtual bases, then bases,
    > > then data members in same order like in class declaration.

    >
    > But your answer "no" does not follow from your explanation.


    Uh? Possibly i misunderstood the topic and the question, then. Order
    in that list does not affect initialization order and so "no" he can
    not initialize other members further on the list unless that list is
    made specially to follow initialization order.

    >
    > I cannot say "yes" for sure, but I often do what the original poster
    > asks for. My compiler (g++) warns me if my initializations aren't in
    > declaration order, so I feel I can safely do it.


    g++ is being helpful there. It helps against bad style. Program, where
    member initializations are in some other order is not ill-formed.
    Standard as i remember was extremely explicit about defending such
    style. I have seen (and cursed) plenty of such code.
     
    Öö Tiib, Aug 17, 2010
    #7
  8. Dwight Army of Champions

    Kai-Uwe Bux Guest

    Öö Tiib wrote:

    > On 17 aug, 20:02, Jorgen Grahn <> wrote:
    >> On Tue, 2010-08-17, Öö Tiib wrote:
    >> > On 17 aug, 17:18, Dwight Army of Champions
    >> > <> wrote:
    >> >> can i use already-initialized data members further on when
    >> >> initializing other members of the member initialization list?

    >>
    >> > No. Order in member initialization list does not affect actual order
    >> > of initialization. Actual order is first virtual bases, then bases,
    >> > then data members in same order like in class declaration.

    >>
    >> But your answer "no" does not follow from your explanation.

    >
    > Uh? Possibly i misunderstood the topic and the question, then. Order
    > in that list does not affect initialization order and so "no" he can
    > not initialize other members further on the list unless that list is
    > made specially to follow initialization order.


    The way, I read the question is whether one can do:

    class range {

    int low;
    int high;

    public:

    range ( int from, int size )
    : low ( from )
    , high ( low + size ) // using already initialized member "low"
    {}

    };

    [...]


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Aug 17, 2010
    #8
  9. Dwight Army of Champions

    Öö Tiib Guest

    On 17 aug, 22:07, Kai-Uwe Bux <> wrote:
    > Öö Tiib wrote:
    > > On 17 aug, 20:02, Jorgen Grahn <> wrote:
    > >> On Tue, 2010-08-17, Öö Tiib wrote:
    > >> > On 17 aug, 17:18, Dwight Army of Champions
    > >> > <> wrote:
    > >> >> can i use already-initialized data members further on when
    > >> >> initializing other members of the member initialization list?

    >
    > >> > No. Order in member initialization list does not affect actual order
    > >> > of initialization. Actual order is first virtual bases, then bases,
    > >> > then data members in same order like in class declaration.

    >
    > >> But your answer "no" does not follow from your explanation.

    >
    > > Uh? Possibly i misunderstood the topic and the question, then. Order
    > > in that list does not affect initialization order and so "no" he can
    > > not initialize other members further on the list unless that list is
    > > made specially to follow initialization order.

    >
    > The way, I read the question is whether one can do:
    >
    >   class range {
    >
    >     int low;
    >     int high;
    >
    >   public:
    >
    >     range ( int from, int size )
    >       : low ( from )
    >       , high ( low + size ) // using already initialized member "low"
    >     {}
    >
    >   };


    Yes, appears i misunderstood it, perhaps because of that "further on".
    As I understand the standard, such constructor must also work when low
    is initialized first.

    range( int from, int size )
    : high( low + size ) // using already initialized member "low"
    , low( from )
    {}
     
    Öö Tiib, Aug 17, 2010
    #9
  10. Öö Tiib wrote:
    > On 17 aug, 22:07, Kai-Uwe Bux <> wrote:
    >> Öö Tiib wrote:
    >>> On 17 aug, 20:02, Jorgen Grahn <> wrote:
    >>>> On Tue, 2010-08-17, Öö Tiib wrote:
    >>>>> On 17 aug, 17:18, Dwight Army of Champions
    >>>>> <> wrote:
    >>>>>> can i use already-initialized data members further on when
    >>>>>> initializing other members of the member initialization list?
    >>>>> No. Order in member initialization list does not affect actual order
    >>>>> of initialization. Actual order is first virtual bases, then bases,
    >>>>> then data members in same order like in class declaration.
    >>>> But your answer "no" does not follow from your explanation.
    >>> Uh? Possibly i misunderstood the topic and the question, then. Order
    >>> in that list does not affect initialization order and so "no" he can
    >>> not initialize other members further on the list unless that list is
    >>> made specially to follow initialization order.

    >> The way, I read the question is whether one can do:
    >>
    >> class range {
    >>
    >> int low;
    >> int high;
    >>
    >> public:
    >>
    >> range ( int from, int size )
    >> : low ( from )
    >> , high ( low + size ) // using already initialized member "low"
    >> {}
    >>
    >> };

    >
    > Yes, appears i misunderstood it, perhaps because of that "further on".
    > As I understand the standard, such constructor must also work when low
    > is initialized first.
    >
    > range( int from, int size )
    > : high( low + size ) // using already initialized member "low"
    > , low( from )
    > {}
    >


    The low is uninitialized, when the high is being initialized. Or I
    misunderstood your reply.

    #include <iostream>
    class range {
    public:
    int high;
    int low;

    range ( int from, int size )
    : high ( low + size ), // using already initialized member "low"
    low ( from )
    {}
    };
    int main()
    {
    range p(5,3);
    std::cout<<"low="<<p.low<<" high="<<p.high<<std::endl;
    }
     
    Vladimir Jovic, Aug 18, 2010
    #10
  11. Vladimir Jovic wrote:
    > Öö Tiib wrote:
    >> On 17 aug, 22:07, Kai-Uwe Bux <> wrote:
    >>> Öö Tiib wrote:
    >>>> On 17 aug, 20:02, Jorgen Grahn <> wrote:
    >>>>> On Tue, 2010-08-17, Öö Tiib wrote:
    >>>>>> On 17 aug, 17:18, Dwight Army of Champions
    >>>>>> <> wrote:
    >>>>>>> can i use already-initialized data members further on when
    >>>>>>> initializing other members of the member initialization list?
    >>>>>> No. Order in member initialization list does not affect actual order
    >>>>>> of initialization. Actual order is first virtual bases, then bases,
    >>>>>> then data members in same order like in class declaration.
    >>>>> But your answer "no" does not follow from your explanation.
    >>>> Uh? Possibly i misunderstood the topic and the question, then. Order
    >>>> in that list does not affect initialization order and so "no" he can
    >>>> not initialize other members further on the list unless that list is
    >>>> made specially to follow initialization order.
    >>> The way, I read the question is whether one can do:
    >>>
    >>> class range {
    >>>
    >>> int low;
    >>> int high;
    >>>
    >>> public:
    >>>
    >>> range ( int from, int size )
    >>> : low ( from )
    >>> , high ( low + size ) // using already initialized member "low"
    >>> {}
    >>>
    >>> };

    >>
    >> Yes, appears i misunderstood it, perhaps because of that "further on".
    >> As I understand the standard, such constructor must also work when low
    >> is initialized first.
    >>
    >> range( int from, int size )
    >> : high( low + size ) // using already initialized member "low"
    >> , low( from )
    >> {}
    >>

    >
    > The low is uninitialized, when the high is being initialized. Or I
    > misunderstood your reply.
    >
    > #include <iostream>
    > class range {
    > public:
    > int high;
    > int low;
    >
    > range ( int from, int size )
    > : high ( low + size ), // using already initialized member "low"
    > low ( from )
    > {}
    > };
    > int main()
    > {
    > range p(5,3);
    > std::cout<<"low="<<p.low<<" high="<<p.high<<std::endl;
    > }


    His example works if you keep the declaration order within the class the
    same (which seems to have been the intention) -- the two key points seem
    to be:

    i) Initialization order depends on the order in which you list the
    members in the class, *not* on the order in the initializer list.

    ii) It's valid to initialize members using other members that precede
    them in the initialization order (but note that the initialization order
    may not be what you initially expect, i.e. see (i)).

    Cheers,
    Stu
     
    Stuart Golodetz, Aug 18, 2010
    #11
  12. Stuart Golodetz wrote:
    > Vladimir Jovic wrote:
    >> Öö Tiib wrote:
    >>> On 17 aug, 22:07, Kai-Uwe Bux <> wrote:
    >>>> Öö Tiib wrote:
    >>>>> On 17 aug, 20:02, Jorgen Grahn <> wrote:
    >>>>>> On Tue, 2010-08-17, Öö Tiib wrote:
    >>>>>>> On 17 aug, 17:18, Dwight Army of Champions
    >>>>>>> <> wrote:
    >>>>>>>> can i use already-initialized data members further on when
    >>>>>>>> initializing other members of the member initialization list?
    >>>>>>> No. Order in member initialization list does not affect actual order
    >>>>>>> of initialization. Actual order is first virtual bases, then bases,
    >>>>>>> then data members in same order like in class declaration.
    >>>>>> But your answer "no" does not follow from your explanation.
    >>>>> Uh? Possibly i misunderstood the topic and the question, then. Order
    >>>>> in that list does not affect initialization order and so "no" he can
    >>>>> not initialize other members further on the list unless that list is
    >>>>> made specially to follow initialization order.
    >>>> The way, I read the question is whether one can do:
    >>>>
    >>>> class range {
    >>>>
    >>>> int low;
    >>>> int high;
    >>>>
    >>>> public:
    >>>>
    >>>> range ( int from, int size )
    >>>> : low ( from )
    >>>> , high ( low + size ) // using already initialized member "low"
    >>>> {}
    >>>>
    >>>> };
    >>>
    >>> Yes, appears i misunderstood it, perhaps because of that "further on".
    >>> As I understand the standard, such constructor must also work when low
    >>> is initialized first.
    >>>
    >>> range( int from, int size )
    >>> : high( low + size ) // using already initialized member "low"
    >>> , low( from )
    >>> {}
    >>>

    >>
    >> The low is uninitialized, when the high is being initialized. Or I
    >> misunderstood your reply.
    >>
    >> #include <iostream>
    >> class range {
    >> public:
    >> int high;
    >> int low;
    >>
    >> range ( int from, int size )
    >> : high ( low + size ), // using already initialized member "low"
    >> low ( from )
    >> {}
    >> };
    >> int main()
    >> {
    >> range p(5,3);
    >> std::cout<<"low="<<p.low<<" high="<<p.high<<std::endl;
    >> }

    >
    > His example works if you keep the declaration order within the class the
    > same (which seems to have been the intention) -- the two key points seem
    > to be:


    Just to clarify, when I said "the same", I meant "the same as in the
    post to which he was replying", i.e. low before high. Your version above
    is the problematic one, because low hasn't been initialized at the point
    where you try and use it to initialize high.

    Kind regards,
    Stu

    > i) Initialization order depends on the order in which you list the
    > members in the class, *not* on the order in the initializer list.
    >
    > ii) It's valid to initialize members using other members that precede
    > them in the initialization order (but note that the initialization order
    > may not be what you initially expect, i.e. see (i)).
    >
    > Cheers,
    > Stu
     
    Stuart Golodetz, Aug 18, 2010
    #12
  13. Stuart Golodetz wrote:
    >> His example works if you keep the declaration order within the class
    >> the same (which seems to have been the intention) -- the two key
    >> points seem to be:

    >
    > Just to clarify, when I said "the same", I meant "the same as in the
    > post to which he was replying", i.e. low before high. Your version above
    > is the problematic one, because low hasn't been initialized at the point
    > where you try and use it to initialize high.


    Thank you for clarification, but next example :

    #include <iostream>
    class range {
    public:
    int low;
    int high;

    range ( int from, int size )
    : high ( low + size ), // using already initialized member "low"
    low ( from )
    {}
    };
    int main()
    {
    range p(5,3);
    std::cout<<"low="<<p.low<<" high="<<p.high<<std::endl;
    }

    fails the compilation with next errors :

    g++ g.cpp -O3 -Wall -Wextra -Werror
    cc1plus: warnings being treated as errors
    g.cpp: In constructor ‘range::range(int, int)’:
    g.cpp:6: error: ‘range::high’ will be initialized after
    g.cpp:5: error: ‘int range::low’
    g.cpp:8: error: when initialized here

    (notice the extra compiler parameters)

    1) Reading OOTib's response (and your), it looks like it should compile
    2) Reading responses from others, it should not compile

    What am I missing?
     
    Vladimir Jovic, Aug 18, 2010
    #13
  14. Vladimir Jovic wrote:
    > Stuart Golodetz wrote:
    >>> His example works if you keep the declaration order within the class
    >>> the same (which seems to have been the intention) -- the two key
    >>> points seem to be:

    >>
    >> Just to clarify, when I said "the same", I meant "the same as in the
    >> post to which he was replying", i.e. low before high. Your version
    >> above is the problematic one, because low hasn't been initialized at
    >> the point where you try and use it to initialize high.

    >
    > Thank you for clarification, but next example :
    >
    > #include <iostream>
    > class range {
    > public:
    > int low;
    > int high;
    >
    > range ( int from, int size )
    > : high ( low + size ), // using already initialized member "low"
    > low ( from )
    > {}
    > };
    > int main()
    > {
    > range p(5,3);
    > std::cout<<"low="<<p.low<<" high="<<p.high<<std::endl;
    > }
    >
    > fails the compilation with next errors :
    >
    > g++ g.cpp -O3 -Wall -Wextra -Werror
    > cc1plus: warnings being treated as errors
    > g.cpp: In constructor ‘range::range(int, int)’:
    > g.cpp:6: error: ‘range::high’ will be initialized after
    > g.cpp:5: error: ‘int range::low’
    > g.cpp:8: error: when initialized here
    >
    > (notice the extra compiler parameters)
    >
    > 1) Reading OOTib's response (and your), it looks like it should compile
    > 2) Reading responses from others, it should not compile
    >
    > What am I missing?


    I guess what you're missing is that things might not compile (despite
    being well-defined) if you set your compiler settings in particular
    ways. In particular, g++ is a compiler that warns you if your member
    declaration order and the order in your initializer list don't match. If
    you enable "treat warnings as errors", the warnings it issues will turn
    into errors, and your code won't compile. That doesn't mean it's not
    well-defined according to the standard, it just means that g++ won't
    compile it with the settings you've chosen.

    There are good arguments for fixing all (sensible) warnings issued by
    your compiler (a few, e.g. a small number of VC++'s more idiotic
    warnings, such as "X inherits Y::f via dominance", should usually be
    disabled to reduce noise that hides genuine warnings). There are also
    some arguments for treating warnings as errors (but I'm personally not
    convinced that they're good arguments unless you're working with people
    who are ill-disciplined). In this case, I would tend to keep g++ happy
    by reordering my initializer list (or the order of member declarations,
    in rare cases). But the code as it stands does work, however confusing
    it might prove to a casual reader.

    [
    Aside:

    I wouldn't like to swear to this (perhaps someone can clarify), but I
    *think* it's the case that the standard doesn't actually say "X should
    compile, Y shouldn't"; rather, it mandates cases in which compilers are
    required to issue a diagnostic (that doesn't necessarily mean they have
    to fail to compile your code, as I understand it). In this case,
    presumably mismatched declaration and initializer list orders isn't one
    of those cases, but g++ chooses to warn you by default anyway.
    ]

    Incidentally, it also compiles for me when the order is wrong:

    struct X
    {
    int b;
    int a;

    X(int a_)
    : a(a_), b(a)
    {}
    };

    int main()
    {
    X x(23);
    return 0;
    }

    So I guess the issue is not primarily one of whether the code compiles
    or not, but of correctness.

    Cheers,
    Stu
     
    Stuart Golodetz, Aug 18, 2010
    #14
  15. On 8/18/2010 11:57 AM, Vladimir Jovic wrote:
    > Thank you for clarification, but next example :
    >
    > #include <iostream>
    > class range {
    > public:
    > int low;
    > int high;
    >
    > range ( int from, int size )
    > : high ( low + size ), // using already initialized member "low"
    > low ( from )
    > {}
    > };
    > int main()
    > {
    > range p(5,3);
    > std::cout<<"low="<<p.low<<" high="<<p.high<<std::endl;
    > }
    >
    > fails the compilation with next errors :
    >
    > g++ g.cpp -O3 -Wall -Wextra -Werror
    > cc1plus: warnings being treated as errors
    > g.cpp: In constructor ‘range::range(int, int)’:
    > g.cpp:6: error: ‘range::high’ will be initialized after
    > g.cpp:5: error: ‘int range::low’
    > g.cpp:8: error: when initialized here
    >
    > (notice the extra compiler parameters)
    >
    > 1) Reading OOTib's response (and your), it looks like it should compile
    > 2) Reading responses from others, it should not compile
    >
    > What am I missing?


    gcc is just warning because the order of initialization that's actually
    going to happen (first range::low then range::high) differs from the
    order in which they are listed in the initializer list. The warning is
    reasonable because it might lead the inexperienced or inattentive reader
    to conclude that high gets initialized first and then low (which is
    wrong). I don't know whose response you understood to mean that it
    should not compile. But it clearly should compile (with less stringent
    compiler parameters anyway) and first set low=from; and then high=low+size;

    "There is a sequence point (1.9) after the initialization of each base
    and member." (12.6.2/3)
    "nonstatic data members shall be initialized in the order they were
    declared in the class definition (again regardless of the order of the
    mem-initializers)." (12.6.2/5)

    Have a nice day,
    Stefan
     
    Stefan van Kessel, Aug 18, 2010
    #15
  16. Dwight Army of Champions

    James Kanze Guest

    On Aug 18, 11:45 am, Stuart Golodetz <> wrote:

    [...]
    > I wouldn't like to swear to this (perhaps someone can
    > clarify), but I *think* it's the case that the standard
    > doesn't actually say "X should compile, Y shouldn't"; rather,
    > it mandates cases in which compilers are required to issue
    > a diagnostic (that doesn't necessarily mean they have to fail
    > to compile your code, as I understand it). In this case,
    > presumably mismatched declaration and initializer list orders
    > isn't one of those cases, but g++ chooses to warn you by
    > default anyway.


    You're basically right. According to the standard, if a program
    is ill-formed, the implementation is required to issue
    a diagnostic message (unless it is explicitely noted that "no
    diagnostic is required" or the standard says that violations
    result in "undefined behavior"). The standard doesn't say what
    happens after that, and since "Undefined behavior may also be
    expected when this International Standard omits the description
    of any explicit definition of behavior", it's formally undefined
    behavior---the compiler can do anything it wishes. (This
    language dates from the C standard, and back when it was
    adopted, one person suggested that a compiler could document
    that it's diagnostic message was to turn the light on on the
    hard disk for an unspecified length of time, and then format the
    hard disk:).)

    The logic behind this is to allow an implementation to "extend"
    the language, making code that would otherwise contain
    diagnosable errors part of the extension. All that was requires
    was that it output a diagnostic (say along the lines of "This
    code uses an extension"); it could then continue, doing whatever
    it liked with the code. (In practice, all of the compilers I've
    seen have preferred to use compiler options, so you can compile
    in strictly conformant mode, and the the compiler is standard
    compliant, or with extensions activated, and the compiler is not
    compliant. IMHO, this is a better solution.)

    Note too that there's nothing to forbid a compiler from
    outputting a diagnostic for a correct program. A lot of
    compilers do sort of distinguish, using the distinction error
    and warning. But the distinction is rarely perfect---a lot of
    compilers will only output warnings for certain types of
    diagnosable errors.

    One additional comment: the standard defines diagnostic message
    as "a message belonging to an implementation-defined subset of
    the implementation’s output messages", and
    implementation-defined behavior as "behavior, for a well-formed
    program construct and correct data, that depends on the
    implementation and that each implementation shall document."
    Note well the last five words: anything that is
    implementation-defined must be documented. I would interpret
    this to mean that the compiler must document which "warnings"
    are due to "diagnosable errors", in the sense of the standard,
    and which concern legal code. I've yet to find this
    documentation for any compiler I've used, however. (G++, for
    example, simply says that any messages that the compiler outputs
    should be considered a diagnostic message in the sense of the
    standard. Which is technically correct, since the standard
    allows a diagnostic message even if there is no error, but it
    certainly ignores the intent of the rules.)

    --
    James Kanze
     
    James Kanze, Aug 19, 2010
    #16
  17. James Kanze wrote:
    > On Aug 18, 11:45 am, Stuart Golodetz <> wrote:
    >
    > [...]
    >> I wouldn't like to swear to this (perhaps someone can
    >> clarify), but I *think* it's the case that the standard
    >> doesn't actually say "X should compile, Y shouldn't"; rather,
    >> it mandates cases in which compilers are required to issue
    >> a diagnostic (that doesn't necessarily mean they have to fail
    >> to compile your code, as I understand it). In this case,
    >> presumably mismatched declaration and initializer list orders
    >> isn't one of those cases, but g++ chooses to warn you by
    >> default anyway.

    >
    > You're basically right. According to the standard, if a program
    > is ill-formed, the implementation is required to issue
    > a diagnostic message (unless it is explicitely noted that "no
    > diagnostic is required" or the standard says that violations
    > result in "undefined behavior"). The standard doesn't say what
    > happens after that, and since "Undefined behavior may also be
    > expected when this International Standard omits the description
    > of any explicit definition of behavior", it's formally undefined
    > behavior---the compiler can do anything it wishes. (This
    > language dates from the C standard, and back when it was
    > adopted, one person suggested that a compiler could document
    > that it's diagnostic message was to turn the light on on the
    > hard disk for an unspecified length of time, and then format the
    > hard disk:).)


    Would this be a compiler running on a DeathStation 9000 by any chance? :)

    > The logic behind this is to allow an implementation to "extend"
    > the language, making code that would otherwise contain
    > diagnosable errors part of the extension. All that was requires
    > was that it output a diagnostic (say along the lines of "This
    > code uses an extension"); it could then continue, doing whatever
    > it liked with the code. (In practice, all of the compilers I've
    > seen have preferred to use compiler options, so you can compile
    > in strictly conformant mode, and the the compiler is standard
    > compliant, or with extensions activated, and the compiler is not
    > compliant. IMHO, this is a better solution.)


    The principle of being able to turn conformance on/off is a good one; in
    practice, though, it can break down if library code isn't
    standard-compliant (e.g. the minute you turn off language extensions in
    VC++, you get whole hosts of errors from legacy Microsoft headers). I
    realise it's not an easy/quick job to fix all those headers, but it does
    rather take away the point of having the option. YMMV of course :)

    > Note too that there's nothing to forbid a compiler from
    > outputting a diagnostic for a correct program. A lot of
    > compilers do sort of distinguish, using the distinction error
    > and warning. But the distinction is rarely perfect---a lot of
    > compilers will only output warnings for certain types of
    > diagnosable errors.
    >
    > One additional comment: the standard defines diagnostic message
    > as "a message belonging to an implementation-defined subset of
    > the implementation’s output messages", and
    > implementation-defined behavior as "behavior, for a well-formed
    > program construct and correct data, that depends on the
    > implementation and that each implementation shall document."
    > Note well the last five words: anything that is
    > implementation-defined must be documented. I would interpret
    > this to mean that the compiler must document which "warnings"
    > are due to "diagnosable errors", in the sense of the standard,
    > and which concern legal code. I've yet to find this
    > documentation for any compiler I've used, however. (G++, for
    > example, simply says that any messages that the compiler outputs
    > should be considered a diagnostic message in the sense of the
    > standard. Which is technically correct, since the standard
    > allows a diagnostic message even if there is no error, but it
    > certainly ignores the intent of the rules.)
    >
    > --
    > James Kanze


    Cheers for the explanation :)
    Stu
     
    Stuart Golodetz, Aug 19, 2010
    #17
  18. Dwight Army of Champions

    Jorgen Grahn Guest

    On Tue, 2010-08-17, Öö Tiib wrote:
    > On 17 aug, 20:02, Jorgen Grahn <> wrote:
    >> On Tue, 2010-08-17, Öö Tiib wrote:
    >> > On 17 aug, 17:18, Dwight Army of Champions
    >> > <> wrote:
    >> >> can i use already-initialized data members further on when
    >> >> initializing other members of the member initialization list?

    >>
    >> > No. Order in member initialization list does not affect actual order
    >> > of initialization. Actual order is first virtual bases, then bases,
    >> > then data members in same order like in class declaration.

    >>
    >> But your answer "no" does not follow from your explanation.

    >
    > Uh? Possibly i misunderstood the topic and the question, then. Order
    > in that list does not affect initialization order and so "no" he can
    > not initialize other members further on the list unless that list is
    > made specially to follow initialization order.


    Sorry for being vague. I meant your "no" should have been "yes, but
    only if it's the declaration order, which it should be anyway". But
    all that got examined later in the thread anyway, so no real harm
    done.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
     
    Jorgen Grahn, Aug 19, 2010
    #18
  19. Dwight Army of Champions

    red floyd Guest

    On Aug 19, 3:48 am, Stuart Golodetz <> wrote:

    > The principle of being able to turn conformance on/off is a good one; in
    > practice, though, it can break down if library code isn't
    > standard-compliant (e.g. the minute you turn off language extensions in
    > VC++, you get whole hosts of errors from legacy Microsoft headers). I
    > realise it's not an easy/quick job to fix all those headers, but it does
    > rather take away the point of having the option. YMMV of course :)
    >


    And of course, that's simply idiocy on Microsoft's part. It would
    have been
    simple to implement a predefined macro _EXTENSIONS_ENABLED or some
    such, when
    extensions are enabled and put the following at the top of windows.h.

    #ifndef _EXTENSIONS_ENABLED
    #error Use of windows.h requires extensions
    #endif

    This would be a much better error message than the host of cascading
    errors
    attempting to compile windows.h in Standard compliant mode provides.
     
    red floyd, Aug 19, 2010
    #19
    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. Replies:
    3
    Views:
    849
    Peter_Julian
    Oct 10, 2005
  2. Replies:
    6
    Views:
    464
    Ron Natalie
    Dec 11, 2005
  3. Angus
    Replies:
    1
    Views:
    2,645
  4. aaragon
    Replies:
    2
    Views:
    621
    James Kanze
    Nov 2, 2008
  5. Marcel Müller
    Replies:
    3
    Views:
    567
    Marcel Müller
    Apr 27, 2009
Loading...

Share This Page