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

Initialization of static varible in class template

P: n/a
I have a C++ template class which contains a static variable whose
construction registers the class with a map. Something like this:

template <typename T>
class M {
static Registrar<M> registrar;
};

The constructor of Registrar does the registering when it is initialized.

My problem is, I can't get this to work for a general class M<T>. I can
get it to work for a specific instance, like M<double>, by including the
initialization definition in the .cpp file:

Registrar< M<double> > M<double>::registrar;

but the general case doesn't work:

template <typename T>
Registrar< M<T> > M<T>::registrar;

It doesn't matter where I put this code --- in the header or .cpp file
--- the Registrar constructor does not get called.

Can anyone tell me where I should put the definition, and whether I need
to do something special with gcc (v3.3) options?

Drew
Jul 22 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Drew McCormack wrote:
I have a C++ template class which contains a static variable whose
construction registers the class with a map. Something like this:

template <typename T>
class M {
static Registrar<M> registrar;
};

The constructor of Registrar does the registering when it is initialized.

My problem is, I can't get this to work for a general class M<T>. I can
get it to work for a specific instance, like M<double>, by including the
initialization definition in the .cpp file:

Registrar< M<double> > M<double>::registrar;

but the general case doesn't work:

template <typename T>
Registrar< M<T> > M<T>::registrar;

It doesn't matter where I put this code --- in the header or .cpp file
--- the Registrar constructor does not get called.

Can anyone tell me where I should put the definition, and whether I need
to do something special with gcc (v3.3) options?


All you need to do is use that 'registrar' somehow. If it's not used,
it's not created. 14.7.1/7 says "The implicit instantiation of a class
template does not cause any static data members of that class to be
implicitly instantiated."

What works, as you described, is the _explicit_ instantiation. Implicit
one doesn't.

As to gcc options, please ask in a gcc newsgroup. Compiler options are
off-topic here.

Victor
Jul 22 '05 #2

P: n/a
Victor Bazarov wrote:
Drew McCormack wrote:
I have a C++ template class which contains a static variable whose
construction registers the class with a map. Something like this:

template <typename T>
class M {
static Registrar<M> registrar;
};

The constructor of Registrar does the registering when it is initialized.

My problem is, I can't get this to work for a general class M<T>. I
can get it to work for a specific instance, like M<double>, by
including the initialization definition in the .cpp file:

Registrar< M<double> > M<double>::registrar;

but the general case doesn't work:

template <typename T>
Registrar< M<T> > M<T>::registrar;

It doesn't matter where I put this code --- in the header or .cpp file
--- the Registrar constructor does not get called.

Can anyone tell me where I should put the definition, and whether I
need to do something special with gcc (v3.3) options?


Hi Victor,
You were right, I needed to use the static variable in my code.
Nonetheless, I am a bit confused as to why this is necessary. Here is why:
All you need to do is use that 'registrar' somehow. If it's not used,
it's not created. 14.7.1/7 says "The implicit instantiation of a class
template does not cause any static data members of that class to be
implicitly instantiated."

I do explicitly instantiate the class template: I use M<double> in my
code, for example. What I wasn't doing is using the static variable
explicitly. Should this be necessary, or is explicitly instantiating the
class template enough?

Drew
Jul 22 '05 #3

P: n/a
Victor Bazarov wrote:
Drew McCormack wrote:
I have a C++ template class which contains a static variable whose
construction registers the class with a map. Something like this:

template <typename T>
class M {
static Registrar<M> registrar;
};

The constructor of Registrar does the registering when it is initialized.

My problem is, I can't get this to work for a general class M<T>. I
can get it to work for a specific instance, like M<double>, by
including the initialization definition in the .cpp file:

Registrar< M<double> > M<double>::registrar;

but the general case doesn't work:

template <typename T>
Registrar< M<T> > M<T>::registrar;

It doesn't matter where I put this code --- in the header or .cpp file
--- the Registrar constructor does not get called.

Can anyone tell me where I should put the definition, and whether I
need to do something special with gcc (v3.3) options?

All you need to do is use that 'registrar' somehow.

One more question: Do you have any suggestions for a clean way to use
the registrar instance in order to force the compiler to create it? At
the moment I am just calling a method of registrar that does nothing
inside the destructor of M<T>, but maybe there is a cleaner way to do it.

Drew
Jul 22 '05 #4

P: n/a
Victor Bazarov wrote:
Drew McCormack wrote:
Victor Bazarov wrote:
Drew McCormack wrote:

I have a C++ template class which contains a static variable whose
construction registers the class with a map. Something like this:

template <typename T>
class M {
static Registrar<M> registrar;
};

The constructor of Registrar does the registering when it is
initialized.

My problem is, I can't get this to work for a general class M<T>. I
can get it to work for a specific instance, like M<double>, by
including the initialization definition in the .cpp file:

Registrar< M<double> > M<double>::registrar;

but the general case doesn't work:

template <typename T>
Registrar< M<T> > M<T>::registrar;

It doesn't matter where I put this code --- in the header or .cpp
file --- the Registrar constructor does not get called.

Can anyone tell me where I should put the definition, and whether I
need to do something special with gcc (v3.3) options?


All you need to do is use that 'registrar' somehow.

One more question: Do you have any suggestions for a clean way to use
the registrar instance in order to force the compiler to create it? At
the moment I am just calling a method of registrar that does nothing
inside the destructor of M<T>, but maybe there is a cleaner way to do it.

What is the purpose of the registrar? Do you intend in the future to
query it somehow to find out how many instances/classes have been created
in the program? If you do query it, you will get your "use" and it will
be instantiated. Until then, put debugging its constructor aside.

Victor

The registrar registers the class in a map, which is used for
serialization. The registrar constructor does this, and it needs to do
it once for each registered class. By including a static instance of
registrar in each class, I intend that the registrar registers the
class, inserting it in the map, before the main program starts.
Jul 22 '05 #5

P: n/a
Victor Bazarov wrote:
Drew McCormack wrote:
Victor Bazarov wrote:
Drew McCormack wrote:

I have a C++ template class which contains a static variable whose
construction registers the class with a map. Something like this:

template <typename T>
class M {
static Registrar<M> registrar;
};

The constructor of Registrar does the registering when it is
initialized.

My problem is, I can't get this to work for a general class M<T>. I
can get it to work for a specific instance, like M<double>, by
including the initialization definition in the .cpp file:

Registrar< M<double> > M<double>::registrar;

but the general case doesn't work:

template <typename T>
Registrar< M<T> > M<T>::registrar;

It doesn't matter where I put this code --- in the header or .cpp
file --- the Registrar constructor does not get called.

Can anyone tell me where I should put the definition, and whether I
need to do something special with gcc (v3.3) options?


Hi Victor,
You were right, I needed to use the static variable in my code.
Nonetheless, I am a bit confused as to why this is necessary. Here is
why:

All you need to do is use that 'registrar' somehow. If it's not used,
it's not created. 14.7.1/7 says "The implicit instantiation of a class
template does not cause any static data members of that class to be
implicitly instantiated."

I do explicitly instantiate the class template: I use M<double> in my
code, for example.

Didn't you initially say that you only had a problem with non-specialised
(not explicitly instantiated) variations of the template? I took it that
you didn't have any problem with 'M<double>::registrar' (and you're not
supposed to, AFAIUI).
> What I wasn't doing is using the static variable

explicitly. Should this be necessary, or is explicitly instantiating
the class template enough?

It's enough to explicitly instantiate the class. But was it the problem
you were running into?

Victor

It works if I explicitly instantiate the static variable:

M<double>::registrar;

But it doesn't work if I just explicitly instantiate the class M:

M<double> mInstance;

The latter does not lead to the static M<double>::registrar being
created. I thought it should, but it doesn't.

Drew
Jul 22 '05 #6

P: n/a
Drew McCormack wrote:
Victor Bazarov wrote:
Drew McCormack wrote:
Victor Bazarov wrote:

Drew McCormack wrote:

> I have a C++ template class which contains a static variable whose
> construction registers the class with a map. Something like this:
>
> template <typename T>
> class M {
> static Registrar<M> registrar;
> };
>
> The constructor of Registrar does the registering when it is
> initialized.
>
> My problem is, I can't get this to work for a general class M<T>.
> I can get it to work for a specific instance, like M<double>, by
> including the initialization definition in the .cpp file:
>
> Registrar< M<double> > M<double>::registrar;
>
> but the general case doesn't work:
>
> template <typename T>
> Registrar< M<T> > M<T>::registrar;
>
> It doesn't matter where I put this code --- in the header or .cpp
> file --- the Registrar constructor does not get called.
>
> Can anyone tell me where I should put the definition, and whether I
> need to do something special with gcc (v3.3) options?

Hi Victor,
You were right, I needed to use the static variable in my code.
Nonetheless, I am a bit confused as to why this is necessary. Here is
why:
All you need to do is use that 'registrar' somehow. If it's not used,
it's not created. 14.7.1/7 says "The implicit instantiation of a class
template does not cause any static data members of that class to be
implicitly instantiated."

I do explicitly instantiate the class template: I use M<double> in my
code, for example.


Didn't you initially say that you only had a problem with non-specialised
(not explicitly instantiated) variations of the template? I took it that
you didn't have any problem with 'M<double>::registrar' (and you're not
supposed to, AFAIUI).
> What I wasn't doing is using the static variable

explicitly. Should this be necessary, or is explicitly instantiating
the class template enough?


It's enough to explicitly instantiate the class. But was it the problem
you were running into?

Victor


It works if I explicitly instantiate the static variable:

M<double>::registrar;

But it doesn't work if I just explicitly instantiate the class M:

M<double> mInstance;

The latter does not lead to the static M<double>::registrar being
created. I thought it should, but it doesn't.


I think you're confused what is an instantiation of what. When you write

M<double> mInstance;

it's an [explicit] instantiation of the class M<double>, but it's not
an explicit instantiation of the template. For the template, it's very
_implicit_. An explicit instantiation of the template would be

template class M<double>;

Yes, it's supposed to work when you explicitly initialise the static data
member itself. However, it should also work when you instantiate the
template explicitly, without explicit instantiation of the static data
member. Example:

template<class T> struct A { static int sa; }; // template definition
template<class T> int A<T>::sa; // definition of the static member

// the following is the explicit instantiation of A<int>
template struct A<int>; // causes A<int>::sa to be instantiated, no
// matter whether you ever have an object of
// type A<int>

// the following is an explicit instantiation of A<char>::sa
template int A<char>::sa;

// the following is an implicit instantiation of A<double> _and_
// an [explicit] instantiation of an object of A<double> type.
A<double> ad; // does NOT instantiate A<double>::sa

What you need to distinguish here is instantiating a template and that
of the resulting class. When you instantiate a class, you create one
object (instance) of that class, which allocates some memory, etc. But
it doesn't cause any code to be created. When you instantiate a template,
the code for _functions_ is created and also static data members are
created (instantiated).

Victor
Jul 22 '05 #7

P: n/a
Victor Bazarov wrote:
Drew McCormack wrote:
Victor Bazarov wrote:
Drew McCormack wrote:

Victor Bazarov wrote:

> Drew McCormack wrote:
>
>> I have a C++ template class which contains a static variable whose
>> construction registers the class with a map. Something like this:
>>
>> template <typename T>
>> class M {
>> static Registrar<M> registrar;
>> };
>>
>> The constructor of Registrar does the registering when it is
>> initialized.
>>
>> My problem is, I can't get this to work for a general class M<T>.
>> I can get it to work for a specific instance, like M<double>, by
>> including the initialization definition in the .cpp file:
>>
>> Registrar< M<double> > M<double>::registrar;
>>
>> but the general case doesn't work:
>>
>> template <typename T>
>> Registrar< M<T> > M<T>::registrar;
>>
>> It doesn't matter where I put this code --- in the header or .cpp
>> file --- the Registrar constructor does not get called.
>>
>> Can anyone tell me where I should put the definition, and whether
>> I need to do something special with gcc (v3.3) options?
>
>
>
>
>

Hi Victor,
You were right, I needed to use the static variable in my code.
Nonetheless, I am a bit confused as to why this is necessary. Here
is why:

>
> All you need to do is use that 'registrar' somehow. If it's not used,
> it's not created. 14.7.1/7 says "The implicit instantiation of a
> class
> template does not cause any static data members of that class to be
> implicitly instantiated."


I do explicitly instantiate the class template: I use M<double> in
my code, for example.


Didn't you initially say that you only had a problem with
non-specialised
(not explicitly instantiated) variations of the template? I took it
that
you didn't have any problem with 'M<double>::registrar' (and you're not
supposed to, AFAIUI).

> What I wasn't doing is using the static variable

explicitly. Should this be necessary, or is explicitly instantiating
the class template enough?


It's enough to explicitly instantiate the class. But was it the problem
you were running into?

Victor

It works if I explicitly instantiate the static variable:

M<double>::registrar;

But it doesn't work if I just explicitly instantiate the class M:

M<double> mInstance;

The latter does not lead to the static M<double>::registrar being
created. I thought it should, but it doesn't.

I think you're confused what is an instantiation of what. When you write

M<double> mInstance;

it's an [explicit] instantiation of the class M<double>, but it's not
an explicit instantiation of the template. For the template, it's very
_implicit_. An explicit instantiation of the template would be

template class M<double>;

Yes, it's supposed to work when you explicitly initialise the static data
member itself. However, it should also work when you instantiate the
template explicitly, without explicit instantiation of the static data
member. Example:

template<class T> struct A { static int sa; }; // template definition
template<class T> int A<T>::sa; // definition of the static member

// the following is the explicit instantiation of A<int>
template struct A<int>; // causes A<int>::sa to be instantiated, no
// matter whether you ever have an object of
// type A<int>

// the following is an explicit instantiation of A<char>::sa
template int A<char>::sa;

// the following is an implicit instantiation of A<double> _and_
// an [explicit] instantiation of an object of A<double> type.
A<double> ad; // does NOT instantiate A<double>::sa

What you need to distinguish here is instantiating a template and that
of the resulting class. When you instantiate a class, you create one
object (instance) of that class, which allocates some memory, etc. But
it doesn't cause any code to be created. When you instantiate a template,
the code for _functions_ is created and also static data members are
created (instantiated).

Victor

OK, now I get it. Thanks. I wasn't up with the explicit/implicit
definitions. Thanks for making that clear.

Cheers,
Drew
Jul 22 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.