Thread: Linking error with static template class members

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    271

    Linking error with static template class members

    The more I think about it, the more I have a feeling I have to change my design but here's the problem, anyway.

    I have a templated class. This class has a static class member variable, which is a templated stl_container. Then there is a class derived from this one that tries to call this member variable in a source file, but results in a linker error. Here's some simplified code:

    Code:
    // in a header file
    template <typename T>
    class A {
    static stl_container<T*>* container;
    };
    
    class B : public A<MyClass> {
    void do_something();
    };
    
    //in a source file
    //memory allocation for "container" is in different source file
    
    void B::do_something() {
    do_something_to(container);
    }
    This gives me a linker error saying it can't find "container" being called from "do_something". Which, if I think about it, makes sense because there is no other object file for it to link from.

    So I can think of one solution which would be to dump the definition of "do_something" into the class body so it doesn't have to resolve the linking error. But I've got other non-class functions that have to access "container" so that's a no go.

    So how do you declare, allocate and use a templated static class variable? Is it possible?

    I need this thing to be static because "class A" is a actually a node in a graph structure that links to other nodes in the graph and info on the overall graph (kept in the container) can be updated by any node.

  2. #2
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    After some googling and tinkering, I've found a solution, but I can't say I understand why it works.

    Code:
    // in a header file
    template <typename T>
    class A {
    static stl_container<T*>* container;
    };
    
    //you need a second declaration outside the body of the class
    //in the header
    template <typename T>
    typename A<T>::stl_container<T*>* container;
    Why you need the second declaration is beyond me. But it works.

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Why is that so surprising? You have to do that even without templates.

    Code:
    class A
    {
    public:
        static int x;
    };
    
    int A::x;
    
    int main()
    {
        A::x = 0;
        return 0;
    }
    How could it be otherwise? How does the compiler magically decide which .cpp module the definition of the static member should come from? The "static int x" is only a declaration -- you still need to define the variable in some specific .cpp module.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  4. #4
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    My previous understanding was that static member variables have to be defined outside the class body, not just declared. Isn't a statement like
    Code:
    int A::x;
    allocating memory as well, and therefore, a definition?

    But when you have a template declaration
    Code:
    template <typename T>
    typename A<T>::stl_container<T*>* container;
    it's not allocating any memory. It's just repeating a declaration made earlier, n'est ce pas? Seems a little byzantine.

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Why should the template syntax deviate from the non-template syntax?
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #6
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    True. Consistency is important.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It's the same as with non-templates.
    It may be a declaration or implementation, but one instantiated, when the class is instantiated, it becomes a definition. That is generally a rule of templates - they are a declaration sorts of, but once instantiated, a definition for those particular types is created.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. LNK2001 ERROR!!! need help
    By lifeafterdeath in forum C++ Programming
    Replies: 7
    Last Post: 05-27-2008, 05:05 PM
  2. template function v.s. template class
    By George2 in forum C++ Programming
    Replies: 3
    Last Post: 12-13-2007, 01:46 AM
  3. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  4. oh me oh my hash maps up the wazoo
    By DarkDays in forum C++ Programming
    Replies: 5
    Last Post: 11-30-2001, 12:54 PM
  5. bug for static functions in template class
    By Unregistered in forum C++ Programming
    Replies: 3
    Last Post: 09-16-2001, 06:38 PM