chgans
9/28/2008 11:26:00 PM
On Sep 28, 8:23 am, James Kanze <james.ka...@gmail.com> wrote:
> 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>::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