Thread: Template class declarations

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

    Template class declarations

    Hello, everyone.

    I'm having some trouble with template class declarations and definitions, especially when they are split across several files.

    As a test example, I did this:

    In file "test.h", I declared:
    Code:
    template<class T>
    class test
    {
    	T t;
    public:
    	void set_t(T k);
    };
    In file "test.cpp", I defined:
    Code:
    #include "test.h"
    
    template<class T>
    void test<T>::set_t(T k)
    {
    	t = k;
    }
    and my main procedure is a very simple:
    Code:
    int _tmain(int argc, _TCHAR* argv[])
    {
    	test<int> p;
    	p.set_t(10);
    	return 0;
    }
    (as you can see, I'm using VC++ 2003)

    The problem is, my compiler keeps giving me a hard time about:
    template_test error LNK2019: unresolved external symbol "public: void __thiscall test<int>::set_t(int)" (?set_t@?$test@H@@QAEXH@Z) referenced in function _main

    It works fine if I just keep the function definition and declaration together, but obviously, I want to know how to split the two.

    Thanks in advance, people.

  2. #2
    Its hard... But im here swgh's Avatar
    Join Date
    Apr 2005
    Location
    England
    Posts
    1,688
    In your main file, are you adding your header file? I am not sure this is the right answer,
    but the linker needs it to find the information to link it together.

    Code:
    // in main function
    #include "test.h"  // is this here?
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	test<int> p;
    	p.set_t(10);
    	return 0;
    }
    This may not be the answer and I appoligise if you have already done this

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    A problem with templates is that the compiler needs to see the template definition (i.e. it's actual implementation) rather than just it's declaration (which you have in your header file).

    For most compilers, this means you need to place the code that you have in test.cpp that implements your set_t function into test.h.

    With some compiler and linker combinations it is possible to avoid the need to do this (using techniques such as "explicit instantiation of templates") but the techniques are compiler dependent.

    Incidentally, _tmain() is VC++ specific. The more portable way is to use a function named main() which returns int.

  4. #4
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    Thank you, grumpy.

    So I take it that there is no way to split the declarations and definitions of class member functions into separate files in VC++?

  5. #5
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Templates are not executable code. The compiler uses them as a recipe to generate executable code. Depending on what template parameters you use in your program, the compiler generates "instances" of the template(or the actual executable code). As a result, the entire recipe should be included in any file that needs to generate instances of the template.

    I'm speculating, but the reasoning for that might go like this. When you include a file, the file is inserted at that point in your program. If you include only the templated declaration of your class, then when the compiler encounters the template declaration, it is able to generate an instance of the class declaration from the parameters in your program. Therefore, you end up with a normal class declaration in your program.

    But, then the compiler hands the program over to the linker to handle making the connections between the functions in the class declaration and the program's function calls, as per normal. Thereafter, the linker goes searching through the other files looking for the function definitions, and maybe when the linker comes across the template definitions, it isn't able to generate code for the functions--that being the compiler's job. As a result, the linker can't find any function definitions that match the function calls in your program, so you get errors.

    On the other hand, if you include both the template for the class declaration as well as the templates for the function definitions, presumably the compiler will generate the specific instances of the declaration as well as all the functions that your program requires. Then the linker can find the actual function definitions and connect them to the function calls in your program.
    Last edited by 7stud; 02-07-2006 at 12:11 PM.

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> So I take it that there is no way to split the declarations and definitions of class member functions into separate files in VC++?

    One common way to do this is to go ahead and split them as you have already done, but at the bottom of your test.h add #include "test.cpp". This might be the only time including a cpp file isn't frowned upon. Some people prefer to give a different extension to source files that contain template definitions rather than using .cpp.

    More info in this FAQ and the ones below it: http://www.parashift.com/c++-faq-lit...html#faq-35.12
    Last edited by Daved; 02-07-2006 at 11:52 AM.

  7. #7
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    One common way to do this is to go ahead and split them as you have already done, but at the bottom of your test.h add #include "test.cpp".
    ...or, equivalently, you could include test.h and then test.cpp(omitting #include test.h in that file) in the main() file.

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I wouldn't do that, though. It is not equivalent in that it places the responsibility of including the source file on the calling code rather than on the implementation itself. Normally you don't include a cpp file, you just include the header file that has the declarations. You want the calling code to continue to follow its normal convention even though the class is templated.

  9. #9
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    As always, 7stud, Daved, you people are amazing.

    Thanks for the help, guys.

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Some compilers support command line options or configuration options (within an IDE) that allow explicit instantiation of templates (eg no need to include the template definition in the header, but needing another file to specify what templates are to be instantiated and have THAT file include the definitions). I'm not sure offhand if VC++ supports such options or not, but a search through help files for command line options or configuration options related to templates will turn up information on such options, if they exist.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Default class template problem
    By Elysia in forum C++ Programming
    Replies: 5
    Last Post: 07-11-2008, 08:44 AM
  2. Declare a template class as a friend?
    By AH_Tze in forum C++ Programming
    Replies: 11
    Last Post: 05-19-2004, 09:24 PM
  3. Prime Number Generator... Help !?!!
    By Halo in forum C++ Programming
    Replies: 9
    Last Post: 10-20-2003, 07:26 PM
  4. Operator overloading in template classes
    By moejams in forum C++ Programming
    Replies: 5
    Last Post: 07-21-2003, 05:16 PM