By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,682 Members | 1,046 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,682 IT Pros & Developers. It's quick & easy.

static class member variables

P: n/a
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! ]
Jul 22 '05 #1
Share this Question
Share on Google+
16 Replies


P: n/a
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.

Jul 22 '05 #2

P: n/a
On 17 Nov 2004 06:12:08 -0500, Eric <sh*****@yahoo.com> 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! ]
Jul 22 '05 #3

P: n/a
"Maxim Yegorushkin" <e-*****@yandex.ru> wrote in message news:<op**************@devlx007.ipcb.net>...

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! ]
Jul 22 '05 #4

P: n/a
Hello Maxim Yegorushkin,

Maxim Yegorushkin schrieb:
On 17 Nov 2004 06:12:08 -0500, Eric <sh*****@yahoo.com> 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! ]

Jul 22 '05 #5

P: n/a
"Maxim Yegorushkin" <e-*****@yandex.ru> wrote in message news:<op**************@devlx007.ipcb.net>...
On 17 Nov 2004 06:12:08 -0500, Eric <sh*****@yahoo.com> 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! ]
Jul 22 '05 #6

P: n/a
"Maxim Yegorushkin" <e-*****@yandex.ru> wrote in message
news:<op**************@devlx007.ipcb.net>...
On 17 Nov 2004 06:12:08 -0500, Eric <sh*****@yahoo.com> 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! ]

Jul 22 '05 #7

P: n/a
On 19 Nov 2004 07:59:16 -0500, Daniel Krügler (ne Spangenberg)
<ds*@bdal.de> 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! ]
Jul 22 '05 #8

P: n/a

"Renjith Mohan" <re**********@hotmail.com> schrieb im Newsbeitrag
news:cd**************************@posting.google.c om...
"Maxim Yegorushkin" <e-*****@yandex.ru> wrote in message
news:<op**************@devlx007.ipcb.net>...
On 17 Nov 2004 06:12:08 -0500, Eric <sh*****@yahoo.com> 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; }

};


Not a clever solution.

v is not tied to class A by any means and can be accessed directly without
any A object / operator ::.
Also, try to use this with multiple translation units, each changing and
reading v (via the functions provided in A). Surprise, surprise (at least
when the semantic of the OP is intended).
Thomas

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #9

P: n/a
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; }

};


An unnamed namespace in a header file? Each of the translation units
that includes it will have its own copy of v, then. :(

--
Seungbeom Kim

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 22 '05 #10

P: n/a
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. The exact meaning of 'return v' is different in every
TU because of the fact that an unnamed namespace does have a name, though
hidden and distinct for every TU.

Aside from (possible) ODR violation, there are other problems. This places
a distinct instance of an object from the unnamed namespace in every TU
that includes the header with the unnamed namespace, what results in quite
different semantics because now every TU operates on an own instance of v.

--
Maxim Yegorushkin

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #11

P: n/a

"Maxim Yegorushkin" <e-*****@yandex.ru> schrieb im Newsbeitrag
news:opshq9w3y9ti5cme@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....


Aside from (possible) ODR violation, there are other problems. This places
a distinct instance of an object from the unnamed namespace in every TU
that includes the header with the unnamed namespace, what results in quite
different semantics because now every TU operates on an own instance of v.


That IS a problem.
Thomas

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Jul 22 '05 #12

P: n/a
"Thomas Mang" <no****@nospam.invalid> wrote...
"Maxim Yegorushkin" <e-*****@yandex.ru> schrieb im Newsbeitrag
news:opshq9w3y9ti5cme@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....


A big misconception. 'v' has _external_ linkage, but it doesn't matter.
Every file that includes that header has its own 'v', since its name has
the name of the anonymous namespace added to it.
[..the other problem is correctly identified..]


V
Jul 22 '05 #13

P: n/a
In article <41***********************@usenet.univie.ac.at>, Thomas Mang
<no****@nospam.invalid> writes
"Maxim Yegorushkin" <e-*****@yandex.ru> schrieb im Newsbeitrag
news:opshq9w3y9ti5cme@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....


It doesn't, it has external linkage but with an unutterable name.
However that is not really relevant because there is a potential ODR
violation which ever way you take it. If the above header file is
included in more than one TU the definition of struct A will be an ODR
issue.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #14

P: n/a
"Maxim Yegorushkin" <e-*****@yandex.ru> wrote in message
news:<opshq9w3y9ti5cme@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. The exact meaning of 'return v' is different in every
TU because of the fact that an unnamed namespace does have a name, though
hidden and distinct for every TU.

Aside from (possible) ODR violation, there are other problems. This places
a distinct instance of an object from the unnamed namespace in every TU
that includes the header with the unnamed namespace, what results in quite
different semantics because now every TU operates on an own instance of v.

I understand my misconception. Thanks for pointing this out. I seem to
have been over enthusiastic about the clause 7.3.1.1 - Unnamed
namespaces para 2 which says something like this
"The use of the static keyword is deprecated when declaring objects in
a namespace scope (see annex depr); the unnamed-namespace provides a
superior alternative."

As has been pointed out this applies to "namespace scope" members only
and even with such variables this must be used with caution as the
generated namespace name(for the unnamed namespace) in each TU is
implementation dependent which may create binary differences of the
executable which is beyond programmers control.

But a doubt remains; since the standard does recommend it for
"namespace scope" variables, does it violate ODR for such variables?.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #15

P: n/a
Thomas Mang wrote:
"Maxim Yegorushkin" <e-*****@yandex.ru> schrieb im Newsbeitrag news:opshq9w3y9ti5cme@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.

--
David Olsen
qg********@yahoo.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Jul 22 '05 #16

P: n/a
re**********@hotmail.com (Renjith Mohan) wrote in message
news:<cd**************************@posting.google. com>...

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! ]
Jul 22 '05 #17

This discussion thread is closed

Replies have been disabled for this discussion.