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

template static member

P: n/a
Hi all,

I'm having difficulties with some template static member, especially
when this member is a template instance, for example:
----
template<typename T>
class BaseT
{
public:
static void UseMap (const std::string &key, int value)
{
std::cout << gName << std::endl;
gMap[key] = value;
}

private:
static const std::string gName;
static std::map<std::string, intgMap;
};

class DerivedT : public BaseT<DerivedT>
{
public:
// Some code soon or late....
};

// Now the specialization for BaseT<DerivedT>

// This one work fine
template<>
const std::string BaseT<DerivedT>::gName("Derived");

// This one gives me a linkage error:
// In function BaseT<DerivedT>::UseMap(...):
// undefined reference to BaseT<DerivedT>::gMap
template<>
std::map<std::string, intBaseT<DerivedT>::gMap;

int main (int argc, char** argv)
{
DerivedT a;
a.UseMap ("test", 4);
}
----

So, i was wandering, if there is a special way to declare a static
member (which use the std::map template) of a template.

Later everything will be split up into several files, but for now i'm
using a single c++ source file to try to solve this problem. I've
tried with g++ 4.3.0 (x86_64, RH FC9) and a arm-linux-g++ 3.4, both
gives same results.

Thanks,
Christian
Sep 27 '08 #1
Share this Question
Share on Google+
5 Replies


P: n/a
chgans wrote:
Hi all,

I'm having difficulties with some template static member, especially
when this member is a template instance, for example:
----
template<typename T>
class BaseT
{
public:
static void UseMap (const std::string &key, int value)
{
std::cout << gName << std::endl;
gMap[key] = value;
}

private:
static const std::string gName;
static std::map<std::string, intgMap;
};

class DerivedT : public BaseT<DerivedT>
{
public:
// Some code soon or late....
};

// Now the specialization for BaseT<DerivedT>

// This one work fine
template<>
const std::string BaseT<DerivedT>::gName("Derived");

// This one gives me a linkage error:
// In function BaseT<DerivedT>::UseMap(...):
// undefined reference to BaseT<DerivedT>::gMap
template<>
std::map<std::string, intBaseT<DerivedT>::gMap;
Why try and specialise?

template <typename T>
std::map<std::string, intBaseT<T>::gMap;

Will be fine.

--
Ian Collins.
Sep 27 '08 #2

P: n/a
On Sep 27, 3:49 pm, chgans <chg...@googlemail.comwrote:
Hi all,

I'm having difficulties with some template static member, especially
when this member is a template instance, for example:
----
template<typename T>
class BaseT
{
public:
static void UseMap (const std::string &key, int value)
{
std::cout << gName << std::endl;
gMap[key] = value;
}

private:
static const std::string gName;
static std::map<std::string, intgMap;

};

class DerivedT : public BaseT<DerivedT>
{
public:
// Some code soon or late....

};

// Now the specialization for BaseT<DerivedT>

// This one work fine
template<>
const std::string BaseT<DerivedT>::gName("Derived");

// This one gives me a linkage error:
// In function BaseT<DerivedT>::UseMap(...):
// undefined reference to BaseT<DerivedT>::gMap
template<>
std::map<std::string, intBaseT<DerivedT>::gMap;

int main (int argc, char** argv)
{
DerivedT a;
a.UseMap ("test", 4);}

----

So, i was wandering, if there is a special way to declare a static
member (which use the std::map template) of a template.

Later everything will be split up into several files, but for now i'm
using a single c++ source file to try to solve this problem. I've
tried with g++ 4.3.0 (x86_64, RH FC9) and a arm-linux-g++ 3.4, both
gives same results.

Thanks,
Christian
It seems that if you specialize a static member you can't do it with a
default constructor. You can either write:

template< class T >
std::map<std::string, intBaseT< T >::gMap;

or:

template<>
std::map<std::string, intBaseT< DerivedT >::gMap( anotherMap );

However, I tested it using only one compiler (g++ 4.1.2) and I did not
look into the Standard so I am not sure that it is what it requires.

Example:

template< class T >
struct A
{
static void
push( T const & v )
{
vec.push_back( v );
}

static std::vector< T vec;
};

template< class T >
std::vector< T A< T >::vec;

/*
template<>
std::vector< double A< double >::vec; // won't work
*/

template<>
std::vector< double A< double >::vec( 10 ); // ok

int
main()
{
A< int >::push( 10 );
A< double >::push( 10.0 );
}

--
Szymon
Sep 27 '08 #3

P: n/a


chgans wrote:
Hi all,
// Now the specialization for BaseT<DerivedT>

// This one work fine
template<>
const std::string BaseT<DerivedT>::gName("Derived");

// This one gives me a linkage error:
// In function BaseT<DerivedT>::UseMap(...):
// undefined reference to BaseT<DerivedT>::gMap
template<>
std::map<std::string, intBaseT<DerivedT>::gMap;
change it into:
template<>
std::map<std::string, intBaseT<DerivedT>::gMap =
std::map<std::string, int>();

to give gMap a memory space.

hth,
Jim
>
int main (int argc, char** argv)
{
DerivedT a;
a.UseMap ("test", 4);
}
----

So, i was wandering, if there is a special way to declare a static
member (which use the std::map template) of a template.

Later everything will be split up into several files, but for now i'm
using a single c++ source file to try to solve this problem. I've
tried with g++ 4.3.0 (x86_64, RH FC9) and a arm-linux-g++ 3.4, both
gives same results.

Thanks,
Christian
Sep 28 '08 #4

P: n/a
On Sep 27, 10:45 pm, SzymonWlodar...@gmail.com wrote:
On Sep 27, 3:49 pm, chgans <chg...@googlemail.comwrote:
I'm having difficulties with some template static member,
especially when this member is a template instance, for
example:
----
template<typename T>
class BaseT
{
public:
static void UseMap (const std::string &key, int value)
{
std::cout << gName << std::endl;
gMap[key] = value;
}
private:
static const std::string gName;
static std::map<std::string, intgMap;
};
class DerivedT : public BaseT<DerivedT>
{
public:
// Some code soon or late....
};
// Now the specialization for BaseT<DerivedT>
// This one work fine
template<>
const std::string BaseT<DerivedT>::gName("Derived");
// This one gives me a linkage error:
// In function BaseT<DerivedT>::UseMap(...):
// undefined reference to BaseT<DerivedT>::gMap
template<>
std::map<std::string, intBaseT<DerivedT>::gMap;
int main (int argc, char** argv)
{
DerivedT a;
a.UseMap ("test", 4);
}
----
So, i was wandering, if there is a special way to declare a
static member (which use the std::map template) of a
template.
It seems that if you specialize a static member you can't do
it with a default constructor. You can either write:
template< class T >
std::map<std::string, intBaseT< T >::gMap;
or:
template<>
std::map<std::string, intBaseT< DerivedT >::gMap( anotherMap );
However, I tested it using only one compiler (g++ 4.1.2) and I
did not look into the Standard so I am not sure that it is
what it requires.
Note that a specialization is not a template, but rather a
declaration or definition of a non-template entity with a name
that looks like a template instantiation, to be used instead of
the instantiation.

Givan that, the basic problem in this is that without an
initializer, the compiler interprets the static member
specialization as a declaration, not a definition, and since
it's not a template, you need a definition (in one, and only
one, translation unit). See §14.7.3/15:

An explicit specialization of a static data member of a
template is a definition if the declaration includes an
initializer; otherwise, it is a declaration. [Note:
there is no syntax for the definition of a static data
member of a template which requires default
initialization.

template<X Q<int>::x ;

This is a declaration regardless of whether X can be
default initialized.]

Note the note!

Note too that formally, you can only provide a single
definition, which means that the definition should be in a
source file, and not in a header; i.e.:

In the header:
template< class T >
std::map< std::string, int BaseT< DerivedT >::gMap ;

and then in one and only one source file (which includes the
header):
template< class T >
std::map< std::string, int BaseT< DerivedT >::gMap(
std::map< std::string, int BaseT< DerivedT >() ) ;
(Luckily, we can use the copy constructor in this case.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 28 '08 #5

P: n/a
On Sep 28, 8:23*am, James Kanze <james.ka...@gmail.comwrote:
On Sep 27, 10:45 pm, SzymonWlodar...@gmail.com wrote:
On Sep 27, 3:49 pm, chgans <chg...@googlemail.comwrote:
I'm having difficulties with some template static member,
especially when this member is a template instance, for
example:
----
template<typename T>
class BaseT
{
public:
* static void UseMap (const std::string &key, int value)
* {
* * std::cout << gName << std::endl;
* * gMap[key] = value;
* }
private:
* static const std::string gName;
* static std::map<std::string, intgMap;
};
class DerivedT : public BaseT<DerivedT>
{
public:
* *// Some code soon or late....
};
// Now the specialization for BaseT<DerivedT>
// This one work fine
template<>
const std::string BaseT<DerivedT>::gName("Derived");
// This one gives me a linkage error:
// In function BaseT<DerivedT>::UseMap(...):
// undefined reference to BaseT<DerivedT>::gMap
template<>
std::map<std::string, intBaseT<DerivedT>::gMap;
int main (int argc, char** argv)
{
* DerivedT a;
* a.UseMap ("test", 4);
}
----
So, i was wandering, if there is a special way to declare a
static member (which use the std::map template) of a
template.
It seems that if you specialize a static member you can't do
it with a default constructor. You can either write:
template< class T >
std::map<std::string, intBaseT< T >::gMap;
or:
template<>
std::map<std::string, intBaseT< DerivedT >::gMap( anotherMap );
However, I tested it using only one compiler (g++ 4.1.2) and I
did not look into the Standard so I am not sure that it is
what it requires.

Note that a specialization is not a template, but rather a
declaration or definition of a non-template entity with a name
that looks like a template instantiation, to be used instead of
the instantiation.

Givan that, the basic problem in this is that without an
initializer, the compiler interprets the static member
specialization as a declaration, not a definition, and since
it's not a template, you need a definition (in one, and only
one, translation unit). *See §14.7.3/15:

* * An explicit specialization of a static data member of a
* * template is a definition if the declaration includes an
* * initializer; otherwise, it is a declaration. [Note:
* * there is no syntax for the definition of a static data
* * member of a template which requires default
* * initialization.

* * * * template<X Q<int>::x ;

* * This is a declaration regardless of whether X can be
* * default initialized.]

Note the note!

Note too that formally, you can only provide a single
definition, which means that the definition should be in a
source file, and not in a header; i.e.:

In the header:
* * template< class T >
* * std::map< std::string, int BaseT< DerivedT >::gMap ;

and then in one and only one source file (which includes the
header):
* * template< class T >
* * std::map< std::string, int BaseT< DerivedT >::gMap(
* * * * * * std::map< std::string, int BaseT< DerivedT >() ) ;
(Luckily, we can use the copy constructor in this case.)
Thank you all,
Problem solved now! :)

>
--
James Kanze (GABI Software) * * * * * * email:james.ka...@gmail.com
Conseils en informatique orientée objet/
* * * * * * * * * *Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 28 '08 #6

This discussion thread is closed

Replies have been disabled for this discussion.