best way to initialize static member objects

C

cppaddict

I have class with two static member objects, one of type int and one
of type vector<int>.

static int myStaticMemberInt
static vector<int> myStaticMemberVector;

I know how to initialize the int member:

MyClass::myStaticMemberInt = 99;

But what is the best way to initialzie myStaticMemberVector?

In particular, the initialization code I want to use is somewhat
complex, and involves processing a series of strings to come up with
each int value for the vector. I'd appreciate any ideas on how to
solve this problem.

Thanks,
cpp
 
D

Dave Townsend

Cpp,



Can you put all this stuff into another static object which can perform your
special initialization of the vector ? That is to say, in the constructor
for the
"mother" object, you can perform some complex C++ to compute the initial
values of the vector.

Alternatively, you could do something like

static vector<int> myStaticMemberVector = foobar();

where foobar is a function returning a vector<int> value which performs
your
necessary setup. I was thinking foobar() would be a free function or static
function
of the class, but I guess it could be a object member function . A variation
on this would
be foobar( string stringarray[]) if the strings involved in the computation
are known at
compile time or can be statically determined.

There might be a few snags in this approach, for instance, the question of
the IO channels
for the program being open and ready to read from the outside, without
knowing a bit more
about your program, I can't say.

dave
 
X

Xenos

cppaddict said:
I have class with two static member objects, one of type int and one
of type vector<int>.

static int myStaticMemberInt
static vector<int> myStaticMemberVector;

I know how to initialize the int member:

MyClass::myStaticMemberInt = 99;

But what is the best way to initialzie myStaticMemberVector?

In particular, the initialization code I want to use is somewhat
complex, and involves processing a series of strings to come up with
each int value for the vector. I'd appreciate any ideas on how to
solve this problem.

Thanks,
cpp

This is just off the top of my head, there are probably better ways (such as
not using statics if you can avoid it!). But what about a function
returning the initialized vector, such as

typedef std::vector<int> int_vector;

extern int_vector init_vector();

static int_vector my_vector = init_vector();

Not efficient in that there is a lot of data movement (unless the compiler
is smart enough to optimize it away), it should work. If that is a problem,
then maybe:

extern int init_vector(int_vector& v);

static int_vector my_vector;
static int temp = init_vector(my_vector);
 
J

JKop

cppaddict posted:
I have class with two static member objects, one of type int and one
of type vector<int>.

static int myStaticMemberInt
static vector<int> myStaticMemberVector;

I know how to initialize the int member:

MyClass::myStaticMemberInt = 99;

But what is the best way to initialzie myStaticMemberVector?

In particular, the initialization code I want to use is somewhat
complex, and involves processing a series of strings to come up with
each int value for the vector. I'd appreciate any ideas on how to
solve this problem.

Thanks,
cpp


Make a class out of the static variable and give it an constructor! One way.

-JKop
 
C

cppaddict

This is just off the top of my head, there are probably better ways (such as
not using statics if you can avoid it!).

Xenos,

What's wrong with static member data? I've never heard anything to
that effect before.

Thanks,
cpp
 
C

cppaddict

Alternatively, you could do something like

static vector<int> myStaticMemberVector = foobar();

where foobar is a function returning a vector<int> value which performs
your
necessary setup. I was thinking foobar() would be a free function or static
function
of the class, but I guess it could be a object member function . A variation
on this would
be foobar( string stringarray[]) if the strings involved in the computation
are known at
compile time or can be statically determined.

I think one of these methods will do what i want.

thanks for your help,
cpp
 
L

Leor Zolman

I have class with two static member objects, one of type int and one
of type vector<int>.

static int myStaticMemberInt
static vector<int> myStaticMemberVector;

I know how to initialize the int member:

MyClass::myStaticMemberInt = 99;

But what is the best way to initialzie myStaticMemberVector?

In particular, the initialization code I want to use is somewhat
complex, and involves processing a series of strings to come up with
each int value for the vector. I'd appreciate any ideas on how to
solve this problem.

Thanks,
cpp

How about making access to the vector be via a static member function,
rather than providing direct access to the vector? That way you can have
the function do initialization the first time it is called. In the
following example, I manipulate the vector through a pointer in main, so I
can re-use the pointer in multiple calls to the static function (which I've
named the same as you named your vector.). The syntax would be cleaner,
though, if I simply used a reference instead of the pointer. But the
implementation of the class and member function would remain the same.

Note also that this example provides no protection for the vector itself;
it may as well be public. To control client operations, you can provide
the usual interface functions (overloaded const and con-const subscript
operators, for example), make myStaticMemberVector() private, and have your
interface functions internally call the static function to get the
initialization behavior you want...

#include <iostream>
#include <vector>

class T
{
public:
static std::vector<int> &myStaticMemberVector();
private:
static int myStaticMemberInt; // = whatever;
static std::vector<int> vector_;
};

std::vector<int> T::vector_;

std::vector<int> &T::myStaticMemberVector()
{
static bool first_time = true;

if (first_time)
{
vector_.push_back(10);
vector_.push_back(20);
vector_.push_back(30);
vector_.push_back(40);
first_time = false;
}

return vector_;
}

int main()
{
using namespace std;
std::vector<int> *vi = &T::myStaticMemberVector();

for (int i = 0; i < vi->size(); i++)
cout << "vector[" << i << "] = " << (*vi) << endl;
cout << endl;

vi->push_back(50);
vi = &T::myStaticMemberVector(); // show no init this time

for (int i = 0; i < vi->size(); i++)
cout << "vector[" << i << "] = " << (*vi) << endl;

return 0;
}

Output:

vector[0] = 10
vector[1] = 20
vector[2] = 30
vector[3] = 40

vector[0] = 10
vector[1] = 20
vector[2] = 30
vector[3] = 40
vector[4] = 50

-leor
 
L

Leor Zolman

I have class with two static member objects, one of type int and one
of type vector<int>.

static int myStaticMemberInt
static vector<int> myStaticMemberVector;

I know how to initialize the int member:

MyClass::myStaticMemberInt = 99;

But what is the best way to initialzie myStaticMemberVector?

In particular, the initialization code I want to use is somewhat
complex, and involves processing a series of strings to come up with
each int value for the vector. I'd appreciate any ideas on how to
solve this problem.

Thanks,
cpp

How about making access to the vector be via a static member function,
rather than providing direct access to the vector? That way you can have
the function do initialization the first time it is called. In the
following example, I manipulate the vector through a pointer in main, so I
can re-use the pointer in multiple calls to the static function (which I've
named the same as you named your vector.). The syntax would be cleaner,
though, if I simply used a reference instead of the pointer. But the
implementation of the class and member function would remain the same.

Note also that this example provides no protection for the vector itself;
it may as well be public. To control client operations, you can provide
the usual interface functions (overloaded const and con-const subscript
operators, for example), make myStaticMemberVector() private, and have your
interface functions internally call the static function to get the
initialization behavior you want...

#include <iostream>
#include <vector>

class T
{
public:
static std::vector<int> &myStaticMemberVector();
private:
static int myStaticMemberInt; // = whatever;
static std::vector<int> vector_;
};

std::vector<int> T::vector_;

std::vector<int> &T::myStaticMemberVector()
{
static bool first_time = true;

if (first_time)
{
vector_.push_back(10);
vector_.push_back(20);
vector_.push_back(30);
vector_.push_back(40);
first_time = false;
}

return vector_;
}

int main()
{
using namespace std;
std::vector<int> *vi = &T::myStaticMemberVector();

for (int i = 0; i < vi->size(); i++)
cout << "vector[" << i << "] = " << (*vi) << endl;
cout << endl;

vi->push_back(50);
vi = &T::myStaticMemberVector(); // show no init this time

for (int i = 0; i < vi->size(); i++)
cout << "vector[" << i << "] = " << (*vi) << endl;

return 0;
}

Output:

vector[0] = 10
vector[1] = 20
vector[2] = 30
vector[3] = 40

vector[0] = 10
vector[1] = 20
vector[2] = 30
vector[3] = 40
vector[4] = 50

-leor
 
C

cppaddict

Leor,

Thank you very much. That is a nice solution. A couple questions....
To control client operations, you can provide
the usual interface functions (overloaded const and con-const subscript
operators, for example),

what are const and con-const subscript operators?

Also, I know you said using ref variables instead of pointer in main
would be cleaner. I am curious why you did use pointers, because the
code that follows works too.

Thanks again for your help,
cpp

PS: I had to change int i to unsigned int i in the loops b/c the
compiler won't allow you to compare signed and unsigned ints (at least
borland won't)


----WORKING ALTERNATIVE------
int main() {
using namespace std;
std::vector<int> vi = T::myStaticMemberVector();

for (unsigned int i = 0; i < vi.size(); i++)
cout << "vector[" << i << "] = " << vi << endl;
cout << endl;

vi.push_back(50);
vi = T::myStaticMemberVector(); // show no init this time

for (unsigned int i = 0; i < vi.size(); i++)
cout << "vector[" << i << "] = " << vi << endl;

return 0;
}
 
L

Leor Zolman

Leor,

Thank you very much. That is a nice solution. A couple questions....


what are const and con-const subscript operators?

Well, if you're providing an interface that includes subscripting
operators, you generally need one that's a non-const member function (that
will be fine for applying to non-const objects), and another that's a const
member function (to allow const objects to be subscripted.).

Let's say you're implementing a class named MyVector, holding ints.. The
relevant portions would go something like this (untested code):

class MyVector {
public:
MyVector(...) {...}; // constructor(s)
int &operator[](size_t i) { return a_; }
const int &operator[](size_t i) const { return a_; }
...
private:
int *a_;
size_t size;
};

The idea is that if you have a const MyVector and you subscript it, the
result should be a reference to a const element, and if you have a
non-const MyVector, it should return a reference to a non-const. Const-ness
is important in C++ so that operations applied to function arguments that
have been declared as reference-to-const will be allowed (as long as
they're read-only):

void foo(const MyVector &mv)
{
cout << "The first value in mv is: " << mv[0] << endl;
}

The Above wouldn't compile if only the non-const operator[] were available,
because you can't invoke a non-const member function on a const object. If
you need to assign through the reference (using a non-const MyVector mv):

mv[0] = 10;

then it would use the non-const overload. I've tried to whittle this issue
down to the bare essentials, but it is rather involved ;-)
Also, I know you said using ref variables instead of pointer in main
would be cleaner. I am curious why you did use pointers, because the
code that follows works too.

But not with the same output, I'd wager. I'll explain down below.
Thanks again for your help,
cpp

Glad to help.
PS: I had to change int i to unsigned int i in the loops b/c the
compiler won't allow you to compare signed and unsigned ints (at least
borland won't)


----WORKING ALTERNATIVE------
int main() {
using namespace std;
std::vector<int> vi = T::myStaticMemberVector();

Above, you're copying an entire vector upon return from the function. After
that, vi has no connection to the vector in the class. They're two separate
vectors.
for (unsigned int i = 0; i < vi.size(); i++)
cout << "vector[" << i << "] = " << vi << endl;
cout << endl;


You wouldn't know that from the output (yet), because your vector vi is a
/copy/ of the one in the class!
vi.push_back(50);

The above changes your vector, not the one in the class.
vi = T::myStaticMemberVector(); // show no init this time

And you're now making yet another copy, and replacing the old vi (yours)
with a copy of the vector from the class.
for (unsigned int i = 0; i < vi.size(); i++)
cout << "vector[" << i << "] = " << vi << endl;


You should not be seeing the value 50 when you run it this way. If you
are, I need to go back to C++ school ;-)

Good luck,
-leor
 
L

Leor Zolman

Leor,

Thank you very much. That is a nice solution. A couple questions....


what are const and con-const subscript operators?

Well, if you're providing an interface that includes subscripting
operators, you generally need one that's a non-const member function (that
will be fine for applying to non-const objects), and another that's a const
member function (to allow const objects to be subscripted.).

Let's say you're implementing a class named MyVector, holding ints.. The
relevant portions would go something like this (untested code):

class MyVector {
public:
MyVector(...) {...}; // constructor(s)
int &operator[](size_t i) { return a_; }
const int &operator[](size_t i) const { return a_; }
...
private:
int *a_;
size_t size;
};

The idea is that if you have a const MyVector and you subscript it, the
result should be a reference to a const element, and if you have a
non-const MyVector, it should return a reference to a non-const. Const-ness
is important in C++ so that operations applied to function arguments that
have been declared as reference-to-const will be allowed (as long as
they're read-only):

void foo(const MyVector &mv)
{
cout << "The first value in mv is: " << mv[0] << endl;
}

The Above wouldn't compile if only the non-const operator[] were available,
because you can't invoke a non-const member function on a const object. If
you need to assign through the reference (using a non-const MyVector mv):

mv[0] = 10;

then it would use the non-const overload. I've tried to whittle this issue
down to the bare essentials, but it is rather involved ;-)
Also, I know you said using ref variables instead of pointer in main
would be cleaner. I am curious why you did use pointers, because the
code that follows works too.

But not with the same output, I'd wager. I'll explain down below.
Thanks again for your help,
cpp

Glad to help.
PS: I had to change int i to unsigned int i in the loops b/c the
compiler won't allow you to compare signed and unsigned ints (at least
borland won't)


----WORKING ALTERNATIVE------
int main() {
using namespace std;
std::vector<int> vi = T::myStaticMemberVector();

Above, you're copying an entire vector upon return from the function. After
that, vi has no connection to the vector in the class. They're two separate
vectors.
for (unsigned int i = 0; i < vi.size(); i++)
cout << "vector[" << i << "] = " << vi << endl;
cout << endl;


You wouldn't know that from the output (yet), because your vector vi is a
/copy/ of the one in the class!
vi.push_back(50);

The above changes your vector, not the one in the class.
vi = T::myStaticMemberVector(); // show no init this time

And you're now making yet another copy, and replacing the old vi (yours)
with a copy of the vector from the class.
for (unsigned int i = 0; i < vi.size(); i++)
cout << "vector[" << i << "] = " << vi << endl;


You should not be seeing the value 50 when you run it this way. If you
are, I need to go back to C++ school ;-)

Good luck,
-leor
 
L

Leor Zolman

Leor,

Thank you very much. That is a nice solution. A couple questions....


what are const and con-const subscript operators?

Well, if you're providing an interface that includes subscripting
operators, you generally need one that's a non-const member function (that
will be fine for applying to non-const objects), and another that's a const
member function (to allow const objects to be subscripted.).

Let's say you're implementing a class named MyVector, holding ints.. The
relevant portions would go something like this (untested code):

class MyVector {
public:
MyVector(...) {...}; // constructor(s)
int &operator[](size_t i) { return a_; }
const int &operator[](size_t i) const { return a_; }
...
private:
int *a_;
size_t size;
};

The idea is that if you have a const MyVector and you subscript it, the
result should be a reference to a const element, and if you have a
non-const MyVector, it should return a reference to a non-const. Const-ness
is important in C++ so that operations applied to function arguments that
have been declared as reference-to-const will be allowed (as long as
they're read-only):

void foo(const MyVector &mv)
{
cout << "The first value in mv is: " << mv[0] << endl;
}

The Above wouldn't compile if only the non-const operator[] were available,
because you can't invoke a non-const member function on a const object. If
you need to assign through the reference (using a non-const MyVector mv):

mv[0] = 10;

then it would use the non-const overload. I've tried to whittle this issue
down to the bare essentials, but it is rather involved ;-)
Also, I know you said using ref variables instead of pointer in main
would be cleaner. I am curious why you did use pointers, because the
code that follows works too.

But not with the same output, I'd wager. I'll explain down below.
Thanks again for your help,
cpp

Glad to help.
PS: I had to change int i to unsigned int i in the loops b/c the
compiler won't allow you to compare signed and unsigned ints (at least
borland won't)


----WORKING ALTERNATIVE------
int main() {
using namespace std;
std::vector<int> vi = T::myStaticMemberVector();

Above, you're copying an entire vector upon return from the function. After
that, vi has no connection to the vector in the class. They're two separate
vectors.
for (unsigned int i = 0; i < vi.size(); i++)
cout << "vector[" << i << "] = " << vi << endl;
cout << endl;


You wouldn't know that from the output (yet), because your vector vi is a
/copy/ of the one in the class!
vi.push_back(50);

The above changes your vector, not the one in the class.
vi = T::myStaticMemberVector(); // show no init this time

And you're now making yet another copy, and replacing the old vi (yours)
with a copy of the vector from the class.
for (unsigned int i = 0; i < vi.size(); i++)
cout << "vector[" << i << "] = " << vi << endl;


You should not be seeing the value 50 when you run it this way. If you
are, I need to go back to C++ school ;-)

Good luck,
-leor
 
C

cppaddict

But not with the same output, I'd wager. I'll explain down below.

You should not be seeing the value 50 when you run it this way. If you
are, I need to go back to C++ school ;-)

Leor,

Indeed you are right. Thanks again for these explanations. They
cleared up quite a bit for me.

cpp
 
S

Siemel Naran

Xenos said:
typedef std::vector<int> int_vector;

extern int_vector init_vector();

static int_vector my_vector = init_vector();

Good idea. If you can declare init_vector in the cpp file, then you don't
clutter the header and don't need extern.
Not efficient in that there is a lot of data movement (unless the compiler
is smart enough to optimize it away), it should work. If that is a problem,
then maybe:

extern int init_vector(int_vector& v);

static int_vector my_vector;
static int temp = init_vector(my_vector);

Also a good idea. One should also consider

class MySingletonVector : private/public/protected std::vector<int> { ... };
// MySingletonVector's constructor does the complex initialization

Use any of the singleton patterns to ensure one instance of
MySingletonVector.
 
S

Siemel Naran

JKop said:
Make a class out of the static variable and give it an constructor! One
way.

Good idea, but to keep the original semantics, install the singleton pattern
in the new class so that you can only create one instance of the class.
 
L

Leor Zolman

Leor,

Indeed you are right. Thanks again for these explanations. They
cleared up quite a bit for me.

Glad to help.

Everyone, I'm sorry for all the duplicate posts; my news server is dying
and I'm waiting for access to info on the new server. In the meantime, I
have to guess whether any posts I make have just been delayed or have
fallen into a black hole. I clearly guessed wrong in this thread :-(
-leor
 
Joined
Jul 8, 2012
Messages
2
Reaction score
0
Dear Leor Zolman,
I used your function, But when i compile my prog, i still get "undefined reference to",Of course i used templated:
Code:
#include "Common/Myclass.h"
#include "test/test.h"
#include <iostream>
#include <typeinfo>
#include <string>
#include <limits>
#include <cstdio>
#include <algorithm>
#include <utility>
#include <functional>
template < class Class, typename ReturnType,typename Parameter1 = int  , typename Parameter2 = int, typename Parameter3 = int, typename  Parameter4 = int >
class Myclass
{
public:
    static std::vector<std::string> eventList  ;
    static std::vector<std::string>  &eventStaticMemberVectorInit();

};
template < >  vector<string> EventHandlerAbstract<test,int, int , int, int , int>::eventList;

template <>
vector<string> &Myclass<test, int, int, int, int, int>::eventStaticMemberVectorInit()
{
    static bool first_time = true;
    //std::vector<std::string> vector_;
    if (first_time)
    {
       eventList.push_back("zero");
       first_time = false;
    }
//    printf("%s \n",eventList[0].c_str());
    return  eventList;
}
int main()
{
std::vector<std::string>  *eventVectorInit = &Myclass<test,int,int,int,int,int>::eventStaticMemberVectorInit();

}
 

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

Staff online

Members online

Forum statistics

Threads
473,775
Messages
2,569,601
Members
45,182
Latest member
BettinaPol

Latest Threads

Top