Thread: templates in different files

  1. #1
    Registered User
    Join Date
    Jun 2003
    Posts
    2

    Angry templates in different files

    Hi all,

    My problem is as follows - (All info code/error etc listed below)

    If I include code parts #1 & #2 in separate files then I get some linker errors (at the end).

    If I include everything in the same file then everything runs ok.

    Pllllleeeeeeeeeeaaaaaaaassssssseeeeeeee help.

    Thanks.

    Code part #1
    Code:
    #include <iostream>
    using namespace std;
    
    template <class T>
    class Stack {
            public:
                    Stack() : index(-1) {}
                    ~Stack() {}
                    void push(T val);
                    T pop();
            private:
                    T data[100];
                    int index;
            };
    Code part #2
    Code:
    template <class T>
    void Stack<T>::push(T val)
    {
            // Increment index, then store
            data[++index] = val;
    }
    template <class T>
    T Stack<T>::pop()
    {
            // Retrieve, then decrement index
            return data[index--];
    }
    The main
    Code:
    #include "stack.h"
    
    int main()
    {
            // Template instantiation
            Stack<int> stack;
            int num;
            int den;
            int val;
            cout << "Enter num: ";
            cin >> num;
            cout << "Enter den: ";
            cin >> den;
            stack.push(num);
            stack.push(den);
            val = stack.pop();
            cout << "popped " << val << endl;
            val = stack.pop();
            cout << "popped " << val << endl;
            return 0;
    }
    The error - link time
    Code:
     % g++ *.C
    Undefined                       first referenced
     symbol                             in file
    Stack<int>::pop()                   /var/tmp/ccA5bKJ2.o
    Stack<int>::push(int)               /var/tmp/ccA5bKJ2.o
    ld: fatal: Symbol referencing errors. No output written to a.out
    collect2: ld returned 1 exit status
    % ls *.C *.h
    stack.C      stack.h      stackMain.C
     %
    The versions
    Code:
     % ld -V
    ld: Software Generation Utilities - Solaris Link Editors: 5.8-1.275
     % g++ -v
    Reading specs from /usr/local/lib/gcc-lib/sparc-sun-solaris2.7/3.0.4/specs
    Configured with: ../gcc-3.0.4/configure 
    Thread model: posix
    gcc version 3.0.4
     %
    Last edited by myname; 06-10-2003 at 04:09 AM.

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    All template definition and implementation code needs to be in a header file that gets included in every file that the template will be used in. The code for a particular variation of a template, for instance a Stack<int> using your code, does not get created until the moment it is instantiated. Because you compile the stack.cpp file (I'm guessing that's the name of it) as a seperate module and you do not create any objects of that type, there is no code for the compiler to generate in that stack.obj module. When you compile the main module, the inclusion of the header file lets the compiler know what the structure of the Stack class is, but during the linker step the linker cannot find any code because it hasn't been generated in stack.obj.

    You could get around this by putting a Stack<int> dummy; declaration at the end of the stack.cpp file which would cause some actual code to be generated for a Stack<int> object in the stack.obj file which would then let linker find this relevant code and link it with the main object file. But this would sort of defeat the purpose of templates because what if you wanted a Stack<float> object? You would then need to add another dummy Stack<float> object instantiation at the end of the file. Well, then what about a Stack built upon other types. You would need to continually modify this file to take into account every possible type of Stack object you would ever expect someone using your code to need.

    The only way around this that I know of currently is to also put all of your template code, definition and implementation, into the header file. That way when you include the stack.hpp file in the main source module, the compiler will have all the necessary stuff to generate the code for whatever particular Stack type you wish to create. So, get rid of the stack.cpp file and put everything that is there into the stack.hpp file.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Supposedly some compilers have ways of getting around this (I've never seen an example, though).

    The proper place to put the bodies of template functions IS within the header file themselves. Think of it this way, in one sense a template is (very loosely) like a macro -- the template does not define code, it defines how the compiler should generate code. So wherever the compiler needs to generate that code, the compiler must have full access to the entirety of the template.

    The way you give the compiler access to the entirety of the template is to put it all within the same header file, and #include it.

  4. #4
    Registered User
    Join Date
    May 2003
    Posts
    148
    >>Supposedly some compilers have ways of getting around this
    Those compilers implementing export reasonable,for example the comeau compiler www.comeaucomputing.com/ or EDG edg.com.

    A interesting article Why we can' afford export (pdf).

  5. #5
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    The GCC Manual has some info on the different ways compilers treat templates.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  6. #6
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    If anyone is interested, here is another article on the subject: Five Compilation Models for C++ Templates
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. *.cpp and *.h files understanding
    By ElastoManiac in forum C++ Programming
    Replies: 4
    Last Post: 06-11-2006, 04:45 AM
  2. Linking header files, Source files and main program(Accel. C++)
    By Daniel Primed in forum C++ Programming
    Replies: 3
    Last Post: 01-17-2006, 11:46 AM
  3. Questions about Templates
    By Shamino in forum C++ Programming
    Replies: 4
    Last Post: 12-18-2005, 12:22 AM
  4. Multiple Cpp Files
    By w4ck0z in forum C++ Programming
    Replies: 5
    Last Post: 11-14-2005, 02:41 PM