static class member variables

Discussion in 'C++' started by Eric, Nov 17, 2004.

  1. Eric

    Eric Guest

    I have a static class member variable as follows:

    struct A
    {
    static void Set (int i) { v = i; }
    static int& Get () { return v; }
    static int v;
    };

    int A::v; // define A::v in the cpp file
    A::v will have external linkage and there will only be one instance of this
    variable in the executable:

    However, let's say I don't want to define the variable in the cpp file (eg.
    it's a template class and I don't want users to have to define the
    variable).
    Is there anything wrong with defining it in a static member function which
    returns a reference to the variable? Will there also always only be one copy
    of the local static variable? Any other unforseen problems? Thanks in
    advance for any comments.

    struct A
    {
    static void Set (int i) { v() = i; }
    static int& Get () { return v(); }
    static int& v()
    {
    static v;
    return v;
    }
    };



    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Eric, Nov 17, 2004
    #1
    1. Advertising

  2. Eric wrote:
    > I have a static class member variable as follows:
    >
    > struct A
    > {
    > static void Set (int i) { v = i; }
    > static int& Get () { return v; }
    > static int v;
    > };
    >
    > int A::v; // define A::v in the cpp file
    > A::v will have external linkage and there will only be one instance of this
    > variable in the executable:
    >
    > However, let's say I don't want to define the variable in the cpp file (eg.
    > it's a template class and I don't want users to have to define the
    > variable).


    You could define the entire template in the header file.

    template <typename X>
    struct A
    {
    static void Set (int i) { v = i; }
    static int& Get () { return v; }
    static int v;
    };

    template <typename X>
    int A::v; // define A::v in the header file


    > Is there anything wrong with defining it in a static member function which
    > returns a reference to the variable? Will there also always only be one copy
    > of the local static variable? Any other unforseen problems? Thanks in
    > advance for any comments.
    >
    > struct A
    > {
    > static void Set (int i) { v() = i; }
    > static int& Get () { return v(); }
    > static int& v()
    > {
    > static v;
    > return v;
    > }
    > };



    In theory, this will work as well, however, some linkers will violate
    the "only one copy" rule when you start using DLL's.

    Having said that, this is the ONLY way to guarentee the order of
    construction in case you're constructing many inter-related objects
    before calling main(), so it is a recomended practice.
    Gianni Mariani, Nov 17, 2004
    #2
    1. Advertising

  3. On 17 Nov 2004 06:12:08 -0500, Eric <> wrote:

    > I have a static class member variable as follows:
    >
    > struct A
    > {
    > static void Set (int i) { v = i; }
    > static int& Get () { return v; }
    > static int v;
    > };
    >
    > int A::v; // define A::v in the cpp file
    > A::v will have external linkage and there will only be one instance of
    > this variable in the executable:
    >
    > However, let's say I don't want to define the variable in the cpp file
    > (eg. it's a template class and I don't want users to have to define the
    > variable).


    You can use a trick to place the static in *.h without getting multiple
    simbol definitions linker error - place that static in a template base
    class as follows:

    template<int dummy> struct statics { static int v; };
    template<int dummy> int statics<dummy>::v;

    struct A : private statics<1234>
    {
    // Get/Set are the same as before
    };

    > Is there anything wrong with defining it in a static member function
    > which returns a reference to the variable? Will there also always only
    > be one copy of the local static variable? Any other unforseen problems?
    > Thanks in
    > advance for any comments.
    >
    > struct A
    > {
    > static void Set (int i) { v() = i; }
    > static int& Get () { return v(); }
    > static int& v()
    > {
    > static v;
    > return v;
    > }
    > };


    Probably, you forgot static keyword here. The code as it is written now
    returns a dangling reference to the already evaporated local variable. You
    can fix it as:

    static int& Get () { static int v; return v; }

    --
    Maxim Yegorushkin

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Maxim Yegorushkin, Nov 18, 2004
    #3
  4. Eric

    James Hopkin Guest

    "Maxim Yegorushkin" <> wrote in message news:<>...
    >
    > You can use a trick to place the static in *.h without getting multiple
    > simbol definitions linker error - place that static in a template base
    > class as follows:
    >
    > template<int dummy> struct statics { static int v; };
    > template<int dummy> int statics<dummy>::v;
    >
    > struct A : private statics<1234>
    > {
    > // Get/Set are the same as before
    > };
    >


    Just a slight tidy up:

    template<int = 0> struct statics { static int v; };
    template<int dummy> int statics<dummy>::v;

    struct A : private statics<>
    {
    // Get/Set are the same as before
    };


    > > Is there anything wrong with defining it in a static member function
    > > which returns a reference to the variable? Will there also always only
    > > be one copy of the local static variable? Any other unforseen problems?
    > > Thanks in
    > > advance for any comments.
    > >
    > > struct A
    > > {
    > > static void Set (int i) { v() = i; }
    > > static int& Get () { return v(); }
    > > static int& v()
    > > {
    > > static v; <------------------ missing int
    > > return v;
    > > }
    > > };

    >
    > Probably, you forgot static keyword here. The code as it is written now
    > returns a dangling reference to the already evaporated local variable. You
    > can fix it as:
    >
    > static int& Get () { static int v; return v; }



    Look again. The only mistake is a missing int on the line I marked
    (which of course will compile on older compilers, since the int was
    implied in pre-standard C++). (Also, Get should probably return by
    value, but that's a design point rather than an error.)


    James

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    James Hopkin, Nov 19, 2004
    #4
  5. Hello Maxim Yegorushkin,

    Maxim Yegorushkin schrieb:

    >On 17 Nov 2004 06:12:08 -0500, Eric <> wrote:
    >
    >
    >>Is there anything wrong with defining it in a static member function
    >>which returns a reference to the variable? Will there also always only
    >>be one copy of the local static variable? Any other unforseen problems?
    >>Thanks in
    >>advance for any comments.
    >>
    >>struct A
    >>{
    >> static void Set (int i) { v() = i; }
    >> static int& Get () { return v(); }
    >> static int& v()
    >> {
    >> static v;
    >> return v;
    >> }
    >>};
    >>
    >>

    >
    >Probably, you forgot static keyword here. The code as it is written now
    >returns a dangling reference to the already evaporated local variable. You
    >can fix it as:
    >
    > static int& Get () { static int v; return v; }
    >

    Your description is somewhat misleading. I think the actual error, the
    OP made was, that its declaration
    of the local static in v misses a type. This looks like an MSVC
    compiler: Its a real **shame** that even MSVC7.1
    does allow implicit int declarations!! (In this case the compiler was
    taking the right "guess", but what about
    the next time??).

    Furtheron it seems reasonable that the OP's Get function signature
    should be changed to

    struct A
    {
    ...
    static int Get () { return v(); }
    ...
    };

    because otherwise The Set function does not make very much sense...

    Last but not least: Your proposal to use the template helper class is a very
    cool idea, Maxim!

    Greetings from Bremen,

    Daniel




    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    =?ISO-8859-1?Q?=22Daniel_Kr=FCgler_=28ne_Spangenbe, Nov 19, 2004
    #5
  6. Eric

    Tokyo Tomy Guest

    "Maxim Yegorushkin" <> wrote in message news:<>...
    > On 17 Nov 2004 06:12:08 -0500, Eric <> wrote:
    > ...
    > > Is there anything wrong with defining it in a static member function
    > > which returns a reference to the variable? Will there also always only
    > > be one copy of the local static variable? Any other unforseen problems?
    > > Thanks in
    > > advance for any comments.
    > >
    > > struct A
    > > {
    > > static void Set (int i) { v() = i; }
    > > static int& Get () { return v(); }
    > > static int& v()
    > > {
    > > static v;
    > > return v;
    > > }
    > > };

    >
    > Probably, you forgot static keyword here.


    Where?

    > The code as it is written now returns a dangling reference to the already
    > evaporated local variable. You can fix it as:
    >
    > static int& Get () { static int v; return v; }


    static int& v () { static int v; return v; } // ?

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Tokyo Tomy, Nov 19, 2004
    #6
  7. "Maxim Yegorushkin" <> wrote in message
    news:<>...
    > On 17 Nov 2004 06:12:08 -0500, Eric <> wrote:
    >
    > > I have a static class member variable as follows:
    > >
    > > struct A
    > > {
    > > static void Set (int i) { v = i; }
    > > static int& Get () { return v; }
    > > static int v;
    > > };
    > >
    > > int A::v; // define A::v in the cpp file
    > > A::v will have external linkage and there will only be one instance of
    > > this variable in the executable:
    > >
    > > However, let's say I don't want to define the variable in the cpp file
    > > (eg. it's a template class and I don't want users to have to define the
    > > variable).

    Another solution is to use an unnamed namespace which is semantically
    equivalent to internal linkage and is a mcuh more simple and elegant
    solution.
    Thus in a header file you can do this.
    namespace
    {
    int v;
    }
    struct A
    {
    static void Set (int i) { v = i; }
    static int& Get () { return v; }

    };

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Renjith Mohan, Nov 19, 2004
    #7
  8. On 19 Nov 2004 07:59:16 -0500, Daniel Krügler (ne Spangenberg)
    <> wrote:

    []

    > Your description is somewhat misleading.


    I agree, that was not a well thought answer.

    > Last but not least: Your proposal to use the template helper class is a
    > very cool idea, Maxim!


    I've stolen the idea from Dinkum STL implementation where it's used for
    std::ios_base::flags (in, out, ate, etc.).

    --
    Maxim Yegorushkin

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Maxim Yegorushkin, Nov 19, 2004
    #8
  9. Eric

    James Hopkin Guest

    (Renjith Mohan) wrote in message
    news:<>...
    >
    > But a doubt remains; since the standard does recommend it for
    > "namespace scope" variables, does it violate ODR for such variables?.
    >


    In this context, you get ODR violations using either (deprecated)
    namespace scope statics or a nameless namespace. Using a nameless
    namespace doesn't make it any more wrong :)

    Point of interest: boost::bind uses a nameless namespace in a header
    to define _1, _2 etc. (the parameter placeholders). I've yet to get a
    grip on the pros and cons of this - not that it's something you have
    to understand to use bind itself.


    James

    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    James Hopkin, Nov 22, 2004
    #9
  10. Eric

    Thomas Mang Guest

    "David Olsen" <> schrieb im Newsbeitrag
    news:...
    > Thomas Mang wrote:
    > > "Maxim Yegorushkin" <> schrieb im Newsbeitrag

    news:eek:pshq9w3y9ti5cme@wkcg6rirwp...
    > >>Renjith Mohan wrote:
    > >>>Another solution is to use an unnamed namespace which is semantically
    > >>>equivalent to internal linkage and is a mcuh more simple and elegant
    > >>>solution.
    > >>>Thus in a header file you can do this.
    > >>>namespace
    > >>>{
    > >>> int v;
    > >>>}
    > >>>struct A
    > >>>{
    > >>> static void Set (int i) { v = i; }
    > >>> static int& Get () { return v; }
    > >>>};
    > >>
    > >>I strongly disagree. I am not sure, but it seems to me, that you've got
    > >>ODR violation here.

    > >
    > > Don't think so. Since v has internal linkage....

    >
    > No, v does not have internal linkage. Things inside the unnamed
    > namespace have external linkage. They just have a name that is known
    > only to the current translation unit, making them inaccessible from
    > other translation units. The ultimate effect is very similar to making
    > v static, but there are some subtle differences that must be understood.
    >
    > The one-definition rule (ODR) violation is not with v, it is with A::Set
    > and A::Get. Within each translation unit, A::Set and A::Get refer to
    > the v that is unique to that translation unit. Therefore, A::Set and
    > A::Get are not the same in all translation units, which is not allowed.


    Thank you.

    I read 3.2 and found an interesting wording in 3.2/5, regarding refering to
    a const object:
    It says ".., except that a name can refer to a const object with internal or
    no linkage if the object has the same integral or enumeration type in all
    definitions of D, and the object is initialized with a constant expression,
    and..."

    Now take these 2 snippets (each in a header file):

    a)

    int const AnInt(5);

    struct bar1
    {
    static int foo() {return AnInt;}
    };


    b)

    double const ADouble(3.1415927);

    struct bar2
    {
    static double foo() {return ADouble;}
    };



    Then a) is fine (when included in > 1 TU), while b) isn't, because the
    constant is floating type.
    Correct?

    If correct, what is the rationale behind discrimination against floating
    types, or e.g. char const[]?


    Thomas



    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]
    Thomas Mang, Nov 24, 2004
    #10
    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. SaravanaKumar
    Replies:
    6
    Views:
    9,358
    Tony Morris
    Oct 19, 2004
  2. E11
    Replies:
    1
    Views:
    4,700
    Thomas Weidenfeller
    Oct 12, 2005
  3. Siemel Naran
    Replies:
    4
    Views:
    783
    Micah Cowan
    Jan 12, 2005
  4. dolphin
    Replies:
    3
    Views:
    1,323
    Pete Becker
    Dec 5, 2007
  5. Replies:
    9
    Views:
    922
Loading...

Share This Page