On Sep 27, 10:45 pm, SzymonWlodar...@gmail.com wrote:
> On Sep 27, 3:49 pm, chgans <chg...@googlemail.com> wrote:
> > 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, int> gMap;
> > };
> > 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, int> BaseT<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, int> BaseT< T >::gMap;
> or:
> template<>
> std::map<std::string, int> BaseT< 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>:

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