initialization of static data member in header file

M

mathieu

Hi there

I am trying to provide a lookup from two 'int's into a char array,
something like this:

template <int g, int e> struct Lookup;
template <> struct Lookup<0,0> {
// some typedef + enums definitions
static const char A;
};
const char Lookup<0,0>::A = "BLA";
// continue with Lookup<0,1> ; Lookup<0,2> ...

Since the initialization is done in the .h file, it gets included
multiple times, and at link time I am getting duplicate symbols.

Is there another way to initialize static data members ? Or could
someone let me know of any work around ?

Thanks for suggestion,
-Mathieu
Ps: Full source code is here:
http://gdcm.svn.sourceforge.net/viewvc/gdcm/trunk/Source/DataDictionary/gdcmTagToType.h?view=markup
 
V

Victor Bazarov

mathieu said:
I am trying to provide a lookup from two 'int's into a char array,
something like this:

template <int g, int e> struct Lookup;
template <> struct Lookup<0,0> {
// some typedef + enums definitions
static const char A;
};
const char Lookup<0,0>::A = "BLA";

You're trying to initialise an object of type 'char' with a character
array. That's impossible. A char array is not convertible to 'char'.
// continue with Lookup<0,1> ; Lookup<0,2> ...

Since the initialization is done in the .h file, it gets included
multiple times, and at link time I am getting duplicate symbols.

Is there another way to initialize static data members ?

Another? Not sure what you mean. Whatever you posted is _not_
a way to initialise it.
Or could
someone let me know of any work around ?

Define and initialise static data in a separate translation unit.
It's not a work-around. It's the only way to do it.

V
 
M

mathieu

You're trying to initialise an object of type 'char' with a character
array. That's impossible. A char array is not convertible to 'char'.

Sorry I meant:

....
static const char A[];
....
Define and initialise static data in a separate translation unit.
It's not a work-around. It's the only way to do it.

Ok. This might be naive, but I was able to do it with typdef and enum,
I tought I could do the same with a char array...
After all I might have to require user of my lib to link to it,
instead of just including it.

-Mathieu
 
V

Victor Bazarov

mathieu said:
You're trying to initialise an object of type 'char' with a character
array. That's impossible. A char array is not convertible to
'char'.

Sorry I meant:

...
static const char A[];
...
Define and initialise static data in a separate translation unit.
It's not a work-around. It's the only way to do it.

Ok. This might be naive, but I was able to do it with typdef and enum,

Not sure what you mean here. Any code sample?
I tought I could do the same with a char array...
After all I might have to require user of my lib to link to it,
instead of just including it.

Static data are special beasts. You can definitely forgo linking if
all you have is code and it's all in templates.

V
 
M

mathieu

Sorry I meant:
...
static const char A[];
...
const char Lookup<0,0>::A[] = "BLA";
Define and initialise static data in a separate translation unit.
It's not a work-around. It's the only way to do it.
Ok. This might be naive, but I was able to do it with typdef and enum,

Not sure what you mean here. Any code sample?

Thanks Victor for taking the time to try to help me out :)
The code is exactly:

http://gdcm.svn.sourceforge.net/viewvc/gdcm/trunk/Source/DataDictionary/gdcmTagToType.h?view=markup

Again I'll use the notion of lookup. From a key (a pair of two
uint16_t) I need to provide extra information. Think of it as a yellow
page, from an integer I need to provide a char array (the name).

template <int Number> struct YellowPage;
template <> struct YellowPage<1234567890> {
enum { Age = 33 };
static const char Name[];
void Print(std::eek:stream &os) { os << Name << " is " << Age << " old
\n"; }
};
const char YellowPage<1234567890>::Name[] = "John Doe";

int main()
{
YellowPage<1234567890> jd;
jd.Print( std::cout );
return 0;
}

Actually I do even need to expose the 'Name', all I need is really the
'Print' function (to an ostream).
Static data are special beasts. You can definitely forgo linking if
all you have is code and it's all in templates.

From your last post, I understood that there is no way to initialize
data, enum were just a special case. Maybe with some ifdef blockers
magic, I should be able to include only once the initilization part...

Thanks
-Mathieu
 
M

mathieu

mathieu said:
mathieu wrote:
I am trying to provide a lookup from two 'int's into a char array,
something like this:
template <int g, int e> struct Lookup;
template <> struct Lookup<0,0> {
// some typedef + enums definitions
static const char A;
};
const char Lookup<0,0>::A = "BLA";
You're trying to initialise an object of type 'char' with a character
array. That's impossible. A char array is not convertible to
'char'.
Sorry I meant:
...
static const char A[];
...
const char Lookup<0,0>::A[] = "BLA";
Define and initialise static data in a separate translation unit.
It's not a work-around. It's the only way to do it.
Ok. This might be naive, but I was able to do it with typdef and enum,
Not sure what you mean here. Any code sample?

Thanks Victor for taking the time to try to help me out :)
The code is exactly:

http://gdcm.svn.sourceforge.net/viewvc/gdcm/trunk/Source/DataDictiona...

Again I'll use the notion of lookup. From a key (a pair of two
uint16_t) I need to provide extra information. Think of it as a yellow
page, from an integer I need to provide a char array (the name).

template <int Number> struct YellowPage;
template <> struct YellowPage<1234567890> {
enum { Age = 33 };
static const char Name[];
void Print(std::eek:stream &os) { os << Name << " is " << Age << " old
\n"; }};

const char YellowPage<1234567890>::Name[] = "John Doe";

int main()
{
YellowPage<1234567890> jd;
jd.Print( std::cout );
return 0;

}

How about simply:

template <int Number> struct YellowPage;
template <> struct YellowPage<1234567890> {
enum { Age = 33 };
const char *GetName() const {
static const char Name[] = "John Doe";
return Name;
}
void Print(std::eek:stream &os) { os << GetName() << " is " << Age << "
years old\n"; }
};

that should do it.

Thanks all, and sorry for the noise
-Mathieu
 
M

mathieu

mathieu wrote:
mathieu wrote:
I am trying to provide a lookup from two 'int's into a char array,
something like this:
template <int g, int e> struct Lookup;
template <> struct Lookup<0,0> {
// some typedef + enums definitions
static const char A;
};
const char Lookup<0,0>::A = "BLA";
You're trying to initialise an object of type 'char' with a character
array. That's impossible. A char array is not convertible to
'char'.
Sorry I meant:
...
static const char A[];
...
const char Lookup<0,0>::A[] = "BLA";
Define and initialise static data in a separate translation unit.
It's not a work-around. It's the only way to do it.
Ok. This might be naive, but I was able to do it with typdef and enum,
Not sure what you mean here. Any code sample?
Thanks Victor for taking the time to try to help me out :)
The code is exactly:

Again I'll use the notion of lookup. From a key (a pair of two
uint16_t) I need to provide extra information. Think of it as a yellow
page, from an integer I need to provide a char array (the name).
template <int Number> struct YellowPage;
template <> struct YellowPage<1234567890> {
enum { Age = 33 };
static const char Name[];
void Print(std::eek:stream &os) { os << Name << " is " << Age << " old
\n"; }};
const char YellowPage<1234567890>::Name[] = "John Doe";
int main()
{
YellowPage<1234567890> jd;
jd.Print( std::cout );
return 0;

How about simply:

template <int Number> struct YellowPage;
template <> struct YellowPage<1234567890> {
enum { Age = 33 };
const char *GetName() const {
static const char Name[] = "John Doe";
return Name;
}
void Print(std::eek:stream &os) { os << GetName() << " is " << Age << "
years old\n"; }

};

that should do it.

Thanks all, and sorry for the noise
-Mathieu

Afterall I needed this one:

static const char *GetName() { return "John Doe"; }

-M
 
J

James Kanze

mathieu said:
mathieu wrote:
I am trying to provide a lookup from two 'int's into a char array,
something like this:
template <int g, int e> struct Lookup;
template <> struct Lookup<0,0> {
// some typedef + enums definitions
static const char A;
};
const char Lookup<0,0>::A = "BLA";
You're trying to initialise an object of type 'char' with a character
array. That's impossible. A char array is not convertible to
'char'.
Sorry I meant:
...
static const char A[];
...
const char Lookup<0,0>::A[] = "BLA";
Define and initialise static data in a separate translation
unit. It's not a work-around. It's the only way to do it.
Ok. This might be naive, but I was able to do it with typdef and enum,
Not sure what you mean here. Any code sample?
Static data are special beasts. You can definitely forgo
linking if all you have is code and it's all in templates.

Not if an explicit specialization is involved, as here.
Explicit specializations are really just normal classes with
funny names, and follow all of the rules of normal classes.
 

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,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top