static class member variables

E

Eric

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;
}
};
 
G

Gianni Mariani

Eric said:
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.
 
M

Maxim Yegorushkin

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; }
 
J

James Hopkin

Maxim Yegorushkin said:
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
};

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
 
?

=?ISO-8859-1?Q?=22Daniel_Kr=FCgler_=28ne_Spangenbe

Hello Maxim Yegorushkin,

Maxim said:
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
 
T

Tokyo Tomy

Maxim Yegorushkin said:
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; } // ?
 
R

Renjith Mohan

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; }

};
 
M

Maxim Yegorushkin

On 19 Nov 2004 07:59:16 -0500, Daniel Krügler (ne Spangenberg)

[]
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.).
 
J

James Hopkin

(e-mail address removed) (Renjith Mohan) wrote in message
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
 
T

Thomas Mang

David Olsen said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,745
Messages
2,569,485
Members
44,909
Latest member
DestinyKetoScam

Latest Threads

Top