static const variables

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Philip Potter

    static const variables

    I'm reading the comp.lang.c++ faq and, though it is incredibly clear and
    lucid in many points, I am completely confused by question 29.6:


    "Here is another even more common example:

    class Fred {
    public:
    ...
    private:
    static const int max_ = 107;
    ...
    };
    In this example, you would need to add the line int Fred::max_; in exactly
    one .cpp file, typically in Fred.cpp."

    Firstly, shouldn't it say "const int Fred::max_"?
    Secondly, it indicates the following code is correct (modulo the _tmain and
    tchar nonsense):

    //foo.cpp
    #include "jimmy.h"
    #include <tchar.h>

    int _tmain(int argc, _TCHAR* argv[]) {
    while(jimmy::fo o==5);
    return 0;
    }

    //jimmy.h
    class jimmy {
    public:
    static const int foo=5;
    };

    //jimmy.cpp
    #include "jimmy.h"
    const int jimmy::foo;


    This code fails to compile under MSVC++, with the following output:

    Compiling...
    foo.cpp

    Linking...

    foo.obj : error LNK2005: "public: static int const jimmy::foo"
    (?foo@jimmy@@2H B) already defined in jimmy.obj

    Is the compiler misbehaving? Or is the FAQ misleading? Or am I just
    confused?

    When I remove the line "const int jimmy::foo;" from jimmy.cpp it compiles
    fine under MSVC++; and if I also replace _tmain() with main(), and TCHAR
    with char and so on, it compiles fine with "g++ -W -Wall -ansi -pedantic
    *.cpp -ofoo". If I am supposed to be defining this static variable in one
    compilation unit, g++ isn't detecting this as non-standard C++.

    I can't find any reference to this in TC++PL, 3rd Ed, to clarify my
    confusion. I've tried checking the index under "static member" and no
    mention is made of the need to define static members in exactly one
    compilation unit.

    What's going on? Do I have to define it or not?

    Philip


  • Victor Bazarov

    #2
    Re: static const variables

    Philip Potter wrote:
    I'm reading the comp.lang.c++ faq and, though it is incredibly clear
    and lucid in many points, I am completely confused by question 29.6:
    >

    "Here is another even more common example:
    >
    class Fred {
    public:
    ...
    private:
    static const int max_ = 107;
    ...
    };
    In this example, you would need to add the line int Fred::max_; in
    exactly one .cpp file, typically in Fred.cpp."
    >
    Firstly, shouldn't it say "const int Fred::max_"?
    Yes, and Marshall will hopefully notice that and correct it.
    Secondly, it indicates the following code is correct (modulo the
    _tmain and tchar nonsense):
    >
    //foo.cpp
    #include "jimmy.h"
    #include <tchar.h>
    >
    int _tmain(int argc, _TCHAR* argv[]) {
    while(jimmy::fo o==5);
    return 0;
    }
    >
    //jimmy.h
    class jimmy {
    public:
    static const int foo=5;
    };
    >
    //jimmy.cpp
    #include "jimmy.h"
    const int jimmy::foo;
    >
    >
    This code fails to compile under MSVC++, with the following output:
    >
    Compiling...
    foo.cpp
    >
    Linking...
    >
    foo.obj : error LNK2005: "public: static int const jimmy::foo"
    (?foo@jimmy@@2H B) already defined in jimmy.obj
    >
    Is the compiler misbehaving? Or is the FAQ misleading? Or am I just
    confused?
    The compier is misbehaving. The Standard requires following the ODR
    and the program does just that.
    When I remove the line "const int jimmy::foo;" from jimmy.cpp it
    compiles fine under MSVC++; and if I also replace _tmain() with
    main(), and TCHAR with char and so on, it compiles fine with "g++ -W
    -Wall -ansi -pedantic *.cpp -ofoo". If I am supposed to be defining
    this static variable in one compilation unit, g++ isn't detecting
    this as non-standard C++.
    There is a proposal on the table that makes it unnecessary to define
    a static integral constant *unless* its address is taken. Your program
    should be valid in either case.
    I can't find any reference to this in TC++PL, 3rd Ed, to clarify my
    confusion. I've tried checking the index under "static member" and no
    mention is made of the need to define static members in exactly one
    compilation unit.
    >
    What's going on? Do I have to define it or not?
    You do, as of now, to be fully standard-compliant. However, you do
    not, with many implementations today, who are (in this regard) running
    ahead of the standardisation process.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask


    Comment

    • Howard

      #3
      Re: static const variables


      "Victor Bazarov" <v.Abazarov@com Acast.netwrote in message
      news:ea803i$9cu $1@news.datemas .de...
      Philip Potter wrote:
      >In this example, you would need to add the line int Fred::max_; in
      >exactly one .cpp file, typically in Fred.cpp."
      >>
      >Firstly, shouldn't it say "const int Fred::max_"?
      >
      Yes, and Marshall will hopefully notice that and correct it.
      >
      >>
      >//jimmy.h
      >class jimmy {
      >public:
      > static const int foo=5;
      >};
      >>
      >//jimmy.cpp
      >#include "jimmy.h"
      >const int jimmy::foo;
      >>

      Victor (et al): doesn't the standard require that the member be initialized
      at the point of definition, not the point of declaration? Every time I've
      seen or used a static const member, the initialization is in the
      implementation code, not in the class definition. I thought this was a
      requirement. (But hey, I've been wrong once or twice before. This morning,
      in fact.)

      Also, could the lack of include guards be affecting the linking here?

      -Howard




      Comment

      • Victor Bazarov

        #4
        Re: static const variables

        Howard wrote:
        [..]
        Victor (et al): doesn't the standard require that the member be
        initialized at the point of definition, not the point of declaration?
        It allows static constants of integral type to be initialised in the
        class definition. (too lazy to look up the paragraph)
        Every time I've seen or used a static const member, the
        initialization is in the implementation code, not in the class
        definition. I thought this was a requirement. (But hey, I've been
        wrong once or twice before. This morning, in fact.)
        >
        Also, could the lack of include guards be affecting the linking here?
        I don't think so. Double inclusion guards need to protect from multiple
        definitions when including the same header in the *same* TU more than
        once (usually through other headers). It's not the case here.

        V
        --
        Please remove capital 'A's when replying by e-mail
        I do not respond to top-posted replies, please don't ask


        Comment

        • Howard

          #5
          Re: static const variables


          "Victor Bazarov" <v.Abazarov@com Acast.netwrote in message
          news:ea82qu$f6l $1@news.datemas .de...
          Howard wrote:
          >[..]
          >Victor (et al): doesn't the standard require that the member be
          >initialized at the point of definition, not the point of declaration?
          >
          It allows static constants of integral type to be initialised in the
          class definition. (too lazy to look up the paragraph)
          Yes, but the post had the initialization in the class definition, and ALSO
          had a definition (without initialization) in the implementation file. When
          initializing in the class definition, is it ok and/or normal to also put a
          definition in the implementation file?

          The OP had this:

          //jimmy.h
          class jimmy {
          public:
          static const int foo=5;
          };

          //jimmy.cpp
          #include "jimmy.h"
          const int jimmy::foo;

          I'm thinking either of the following would fix things:

          //jimmy.h
          class jimmy {
          public:
          static const int foo;
          };

          //jimmy.cpp
          #include "jimmy.h"
          const int jimmy::foo=5;

          ....or...

          //jimmy.h
          class jimmy {
          public:
          static const int foo=5;
          };

          //jimmy.cpp
          #include "jimmy.h"

          -Howard


          Comment

          • Victor Bazarov

            #6
            Re: static const variables

            Howard wrote:
            "Victor Bazarov" <v.Abazarov@com Acast.netwrote in message
            news:ea82qu$f6l $1@news.datemas .de...
            >Howard wrote:
            >>[..]
            >>Victor (et al): doesn't the standard require that the member be
            >>initialized at the point of definition, not the point of
            >>declaration ?
            >>
            >It allows static constants of integral type to be initialised in the
            >class definition. (too lazy to look up the paragraph)
            >
            Yes, but the post had the initialization in the class definition, and
            ALSO had a definition (without initialization) in the implementation
            file. When initializing in the class definition, is it ok and/or
            normal to also put a definition in the implementation file?
            Not only it's OK. It's *required* by the current Standard.

            Please don't make me leaf through the Standard. Get yourself a copy
            and find the exact wording, and then read the archives about the new
            proposal that makes it unnecessary to define the static const integral
            member if it's not used as an lvalue.

            V
            --
            Please remove capital 'A's when replying by e-mail
            I do not respond to top-posted replies, please don't ask


            Comment

            • red floyd

              #7
              Re: static const variables

              Victor Bazarov wrote:
              Howard wrote:
              >[..]
              >Victor (et al): doesn't the standard require that the member be
              >initialized at the point of definition, not the point of declaration?
              >
              It allows static constants of integral type to be initialised in the
              class definition. (too lazy to look up the paragraph)
              9.4.2/4

              Just had to look that up yesterday to beat someone over the head with :)
              They were trying to inline initialize a static const double.

              Comment

              • Frederick Gotham

                #8
                Re: static const variables

                Philip Potter posted:
                foo.obj : error LNK2005: "public: static int const jimmy::foo"
                (?foo@jimmy@@2H B) already defined in jimmy.obj

                Your compiler/linker/whatever is Microsoftsque.


                9.4.2/4

                If a static data member is of const integral or const enumeration type, its
                declaration in the class definition can specify a constant-initializer which
                shall be an integral constant expression. In that case, the member can appear
                in integral constant expressions. The member shall still be defined in a
                namespace scope if it is used in the program and the namespace scope
                definition shall not contain an initializer.

                --

                Frederick Gotham

                Comment

                • Andrey Tarasevich

                  #9
                  Re: static const variables

                  Howard wrote:
                  ...
                  Yes, but the post had the initialization in the class definition, and ALSO
                  had a definition (without initialization) in the implementation file. When
                  initializing in the class definition, is it ok and/or normal to also put a
                  definition in the implementation file?
                  ...
                  Yes, the language (as described in C++98) makes an exception for static const
                  members of integral and enum types - they can be supplied with an initializer in
                  the class definition. Note, that presence of the initializer does not turn the
                  declaration of such a member into a definition, meaning that the separate
                  definition (without an initializer) is still required. (The updated standard
                  made (TC1?) some updates to that specification, as Victor already mentioned.)

                  In other words, the user can choose where to put the initializer for static
                  const member of integral or enum type. One important detail here is that when
                  the initializer is supplied in the class definition, the const member can be
                  used as an integral constant expression (ICE) everywhere in the program. When
                  the initializer is supplied at the point of member definition, it might only be
                  used as an ICE in that translation unit where it is defined, and it is not an
                  ICE anywhere else.

                  The practice to put the initializer at the point of member definition was/is
                  popular because certain compilers refused to accept initializers in class
                  definition.

                  --
                  Best regards,
                  Andrey Tarasevich

                  Comment

                  • Philip Potter

                    #10
                    Re: static const variables

                    "Victor Bazarov" <v.Abazarov@com Acast.netwrote in message
                    news:ea803i$9cu $1@news.datemas .de...
                    Philip Potter wrote:
                    Is the compiler misbehaving? Or is the FAQ misleading? Or am I just
                    confused?
                    >
                    The compier is misbehaving. The Standard requires following the ODR
                    and the program does just that.
                    Thank you very much for a clear response! It seems like an ugly language
                    feature. What is the ODR?
                    When I remove the line "const int jimmy::foo;" from jimmy.cpp it
                    compiles fine under MSVC++; and if I also replace _tmain() with
                    main(), and TCHAR with char and so on, it compiles fine with "g++ -W
                    -Wall -ansi -pedantic *.cpp -ofoo". If I am supposed to be defining
                    this static variable in one compilation unit, g++ isn't detecting
                    this as non-standard C++.
                    >
                    There is a proposal on the table that makes it unnecessary to define
                    a static integral constant *unless* its address is taken. Your program
                    should be valid in either case.
                    Hooray!
                    I can't find any reference to this in TC++PL, 3rd Ed, to clarify my
                    confusion. I've tried checking the index under "static member" and no
                    mention is made of the need to define static members in exactly one
                    compilation unit.

                    What's going on? Do I have to define it or not?
                    >
                    You do, as of now, to be fully standard-compliant. However, you do
                    not, with many implementations today, who are (in this regard) running
                    ahead of the standardisation process.
                    Well, I've patched up the code by placing #ifndef _MSC_VER / #endif around
                    the jimmy.cpp definition line; though I wonder if it's really worth the
                    effort.

                    Philip


                    Comment

                    • Howard

                      #11
                      Re: static const variables


                      "Andrey Tarasevich" <andreytarasevi ch@hotmail.comw rote in message
                      news:12cf6t4cck u0116@news.supe rnews.com...
                      Howard wrote:
                      >...
                      >Yes, but the post had the initialization in the class definition, and
                      >ALSO
                      >had a definition (without initialization) in the implementation file.
                      >When
                      >initializing in the class definition, is it ok and/or normal to also put
                      >a
                      >definition in the implementation file?
                      >...
                      >
                      Yes, the language (as described in C++98) makes an exception for static
                      const
                      members of integral and enum types - they can be supplied with an
                      initializer in
                      the class definition. Note, that presence of the initializer does not turn
                      the
                      declaration of such a member into a definition, meaning that the separate
                      definition (without an initializer) is still required. (The updated
                      standard
                      made (TC1?) some updates to that specification, as Victor already
                      mentioned.)
                      >
                      In other words, the user can choose where to put the initializer for
                      static
                      const member of integral or enum type. One important detail here is that
                      when
                      the initializer is supplied in the class definition, the const member can
                      be
                      used as an integral constant expression (ICE) everywhere in the program.
                      When
                      the initializer is supplied at the point of member definition, it might
                      only be
                      used as an ICE in that translation unit where it is defined, and it is not
                      an
                      ICE anywhere else.
                      >
                      The practice to put the initializer at the point of member definition
                      was/is
                      popular because certain compilers refused to accept initializers in class
                      definition.
                      >
                      --
                      Best regards,
                      Andrey Tarasevich
                      Thanks for the clarification, Andrey.

                      -Howard



                      Comment

                      • Howard

                        #12
                        Re: static const variables


                        "Victor Bazarov" <v.Abazarov@com Acast.netwrote in message
                        news:ea84pr$imv $1@news.datemas .de...
                        Howard wrote:
                        >"Victor Bazarov" <v.Abazarov@com Acast.netwrote in message
                        >news:ea82qu$f6 l$1@news.datema s.de...
                        >>Howard wrote:
                        >>>[..]
                        >>>Victor (et al): doesn't the standard require that the member be
                        >>>initialize d at the point of definition, not the point of
                        >>>declaratio n?
                        >>>
                        >>It allows static constants of integral type to be initialised in the
                        >>class definition. (too lazy to look up the paragraph)
                        >>
                        >Yes, but the post had the initialization in the class definition, and
                        >ALSO had a definition (without initialization) in the implementation
                        >file. When initializing in the class definition, is it ok and/or
                        >normal to also put a definition in the implementation file?
                        >
                        Not only it's OK. It's *required* by the current Standard.
                        Ok, good to know.
                        >
                        Please don't make me leaf through the Standard. Get yourself a copy
                        and find the exact wording, and then read the archives about the new
                        proposal that makes it unnecessary to define the static const integral
                        member if it's not used as an lvalue.
                        >
                        Andrey provided a good explanation. I've tried looking at the Standard, but
                        it makes my head spin. I'm good at coding, but I just can't seem to
                        understand that kind of "legalese". Thanks anyway...

                        -Howard



                        Comment

                        • Victor Bazarov

                          #13
                          Re: static const variables

                          Philip Potter wrote:
                          [..] What is the ODR?
                          One Definition Rule.
                          [..]
                          V
                          --
                          Please remove capital 'A's when replying by e-mail
                          I do not respond to top-posted replies, please don't ask


                          Comment

                          Working...