CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2
  1. #1
    Join Date
    May 2010
    Posts
    6

    Not sure what it is that I'm doing wrong with templates in this case

    Hi, I'm having a weird problem with templates. Here is the linker error that I'm getting (in bold):
    Code:
    % make clean && time make
    rm -rf *o main
    g++ -c -g generic-stack.cpp
    g++ -c -g main.cpp
    g++ -c -g stack.cpp
    g++ -c -g enhanced-stack.cpp
    g++ -c -g base-stack.cpp
    g++ -c -g array-stack.cpp
    g++ -c -g list-stack.cpp
    g++ main.o generic-stack.o stack.o enhanced-stack.o base-stack.o array-stack.o list-stack.o -o main
    Undefined symbols for architecture x86_64:
      "GENERIC_STACK<int>::GENERIC_STACK()", referenced from:
          _main in main.o
      "GENERIC_STACK<int>::~GENERIC_STACK()", referenced from:
          _main in main.o
    ld: symbol(s) not found for architecture x86_64
    collect2: ld returned 1 exit status
    make: *** [main] Error 1
    Here is the header file:
    Code:
    #ifndef GENERIC_STACK_HPP
    #define GENERIC_STACK_HPP
    
    #include "global-includes.hpp"
    
    template <typename T>
    class GENERIC_STACK
    {
      public:
        GENERIC_STACK();
        ~GENERIC_STACK();
        void Push(T value);
        T Pop();
        bool Is_Empty();
    
      private:
      protected:
        struct NODE
        {
          T value;
          NODE * link;
        };
    
        NODE * Head;
    };
    
    #endif
    Here is a source file:
    Code:
    #include "generic-stack.hpp"
    
    template <typename T>
    GENERIC_STACK<T>::GENERIC_STACK()
    {
      Head = NULL;
    }
    
    template <typename T>
    GENERIC_STACK<T>::~GENERIC_STACK()
    {
      T value;
    
      while(!Is_Empty())
      {
        Pop(value);
      }
    }
    
    template <typename T>
    void GENERIC_STACK<T>::Push(T value)
    {
      NODE * temp = new NODE;
      temp->value = value;
      temp->link = Head;
      Head = temp;
    }
    
    template <typename T>
    T GENERIC_STACK<T>::Pop()
    {
      T value;
      NODE * temp = Head;
      value = Head->value;
      Head = Head->link;
      delete temp;
    }
    
    template <typename T>
    bool GENERIC_STACK<T>::Is_Empty()
    {
      return Head == NULL;
    }
    This is the main method:
    Code:
    #include "new-stack.hpp"
    #include "list-stack.hpp"
    #include "array-stack.hpp"
    #include "generic-stack.hpp"
    
    int main(int argc, char * argv[])
    {
      ...
    
    
      GENERIC_STACK<int> int_stack;
    
      return 0;
    }
    Two things I'd like to add:
    1 - I know that standards-wise, this code is ugly. This is just my temporary thing that I'm using to remember about C++.
    2 - "global-includes.hpp" includes stuff like #include <iostream>, etc.

    Now, my question, why am I getting this ugly error? I've checked my Makefile and that looks good (below) and I don't understand why this is happening.

    Makefile
    Code:
    all: main
    
    main: generic-stack.o main.o stack.o enhanced-stack.o base-stack.o array-stack.o list-stack.o
    	g++ main.o generic-stack.o stack.o enhanced-stack.o base-stack.o array-stack.o list-stack.o -o main
    
    generic-stack.o: generic-stack.cpp
    	g++ -c -g generic-stack.cpp
    
    base-stack.o: base-stack.cpp
    	g++ -c -g base-stack.cpp
    
    array-stack.o: array-stack.cpp
    	g++ -c -g array-stack.cpp
    
    list-stack.o: list-stack.cpp
    	g++ -c -g list-stack.cpp
    
    stack.o: stack.cpp
    	g++ -c -g stack.cpp
    
    enhanced-stack.o: enhanced-stack.cpp
    	g++ -c -g enhanced-stack.cpp
    
    new-stack.o: new-stack.cpp
    	g++ -c -g new-stack.cpp
    
    main.o: main.cpp
    	g++ -c -g main.cpp
    
    clean:
    	rm -rf *o main
    Thoughts?

    Yes, I googled, no I could not find an answer that helped me.

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Not sure what it is that I'm doing wrong with templates in this case

    The template implementation must be visible at the time of instantiation. This is the case for almost every single compiler out there.

    What you did was separate the implementation from the interface, and then compiled the implementation into separate modules. This is not correct. You must include the implementation with the interface. If you want an example, open up the <vector> or <list> file and see how these classes are implemented. You will see the entire code is within the header.

    So either place the code inline into the template class, or #include the implementation at the end of your .h files. In any event, you also have to make sure you do not compile separate template modules as you're doing now. They are not separable compilation units.

    As far as not finding things on google -- there must be thousands of easily found links saying this about templates. Here is one right here on this board:

    http://forums.codeguru.com/showthrea...-template-code

    Here are more links:
    http://www.parashift.com/c++-faq/tem...n-vs-decl.html
    http://www.parashift.com/c++-faq/sep...from-decl.html
    http://www.parashift.com/c++-faq/sep...t-keyword.html

    In addition, there have countless threads with the same question concerning templates, all answered in the same way (which is why a FAQ was created for this years ago).

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; April 7th, 2013 at 11:10 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured