How exactly should template classes be defined and implemented properly in C++? - c++

I recently decided to do some personal C++ practice by writing simple structures to ease into C++ development. My first attempt was to write a simple LinkedList but define it as a template class so that it could handle multiple data types. While doing so I did the standard practice of defining the class in a header file and implementing it in a cpp file and then I used make to build it (with 686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1). As far as building the C++ files (which included a Node.cpp, LinkedList.cpp and LinkedListIterator.cpp everything worked fine with no complaints. I then introduce main.cpp which contained the main method and tried to create a LinkedList<string> (which worked) and then tried to call it's length function which I both defined and implemented:
// Other code here
LinkedList<string> *list = new LinkedList<string>();
cout << "Initial length: " << list->length() << endl;
delete list;
list = NULL; // I had defined NULL to be 0, pre 4.6 compiler so nullptr wasn't available
// End the main function
This threw an error that no length() function was defined for the templated LinkedList<string> class and so I began my research where I learned that template classes cannot be defined in the standard header/implementation format like standard C++ classes but none of these responses (mostly here) addressed how to properly handle template classes. So to finish off my personal exercise I dropped the headers and just defined and implemented the classes in the cpp file. Everything worked fine there.
There were some "work arounds" that supposedly made it possible to separate implementation from definition such as including the cpp file at the end of the header file (which failed to work for me) or, provided you only want your class to work with specific types, to declare static template versions of your class at the base of your header file like:
// Define a template class
template LinkedList<string>;
template LinkedList<int>;
// etc...
Which I didn't try (it may have worked, and as I was only doing a personal exercise it was perfectly acceptable) because this just feels wrong. Why make a template class if you lock it into certain types? I realize you could easily lock it into to all the major types you need giving you one definition for several data types but it just doesn't sit right with me to do things this way.
TL;DR Ultimately my question is, what is the proper way to define a template class and implement a template class in some kind of application/library other people would be using?

You need to put everything - class definition and the class code - in the header. To see why, imagine a simple case:
// in .hpp
template <typename T>
T increment(T x);
// in .cpp
template <typename T>
T increment(T x) { return x + 1; }
Now you compile the .cpp only once. What code is it supposed to generate for the increment function? The + operator could be a floating point addition, or an integer addition, or a short integer, or even an overloaded operator+.
Then think about some other .cpp file where you're using the increment function:
// some other .cpp file
#include "increment.hpp"
...
increment(a);
At this point, the compiler knows what type a is, so it could then generate the correct code for the increment function. But it doesn't know what the increment function looks like because it only sees the .hpp file and the code for increment is in the .cpp file.
Therefore, the only way to make it work is to put the declaration and the code in the .hpp file so that every time you use it, you have the definition and the compiler can generate the right version for the type you're using.

Templates must be visible at the point of instantiation. Without explicit instantiation that basically means that the member function definitions must be available in the header for other translation units to instantiate it.

Related

C++ Two Classes Template Methods Reference (Not Compose) Each Other

I've gotten into a bit of a design block in a C++ program of mine as two different header files are required to reference each other. Typically a forward declaration would be used here, but since both classes use template functions/constructors a forward declaration cannot be used as methods/variables from both classes need to be used.
For example consider the following scenario (this is pseudo code as an example, it may/may not compile. The objects are representative of my actual application so if a redesign is necessary then I'd love to understand the design philosophies of what I did wrong)
// Application.hpp
#include <Assets.hpp>
#include <Logger.hpp>
class Application {
public:
// Some brilliant code here ...
Logger myLogger;
template <int someArrayLen> Application(std::array<int, someArrayLen> myArr, SomeOtherTypes someOtherStuff) : myLogger(stuffHere) {
mainAssets = new Assets(myArr);
}
~Application(); // Assume this is implemented in Application.cpp and has delete mainAssets;
};
extern Application* mainApp; // Assume Application* mainApp = nullptr; in Application.cpp
// Assets.hpp
// #include <Application.hpp> ???? The issue lies here
class Assets {
private:
// Random data structures/stuff for holding shaders/textures/etc
protected:
template <int someArrayLen> Assets(std::array<int, someArrayLen> myArr) {
if (!shadersSupported()) {
// Main app is an unknown symbol
mainApp->myLogger->error("Your GPU is too old/whatever!");
}
// Random code for loading assets based on my template stuff
}
friend class Application;
public:
// Get assets/whatever here
};
extern Assets* mainAssets; // Assume Assets* mainAssets = nullptr; in Assets.cpp
How can I fix the compile error regarding mainApp being an unknown symbol? Any feedback/help is appreciated, thanks!
I've already looked through all the following questions but none address this unique scenario:
two classes referencing each other
This question had no use of templates so forward declarations could be used as the method bodies weren't defined in the headers
Two classes referencing each other with hash template specialization
The solution from this question cannot be used as here the compiler was unable to figure out how much memory to allocate, whereas in my question the issue isn't regarding the compiler being confused with how much to allocate but rather what to reference
Two template classes being composed of a member of each other
This question addressed a design flaw of circular dependencies which my application does not have, both classes are stored globally, they are just instantiated in separate constructors which reference each other.
Two classes that refer to each other
This question provides forward declarations as a solution which cannot be used here due to the requirement for using the class methods/constructors in template function definitions.
I've also already considered the following:
Trying to change from std::array to pointers, this wouldn't work as my Assets constructor does rely on the lengths of the array.
Trying to change from std::array to std::vector, I want to stick to aggregate initialization so it can be done at compile time, I believe vectors/lists would be too heavy for this.
Forward declarations will indeed work for your problem. The key is that function templates can be defined out of line (i.e., not in your class ... { }; declaration) legally. The same can be achieved for arbitrary functions using the inline keyword.
To now solve your specific problem, just split Application.hpp into Applicaton_fwd.hpp and Application.hpp - similar to iosfwd. Application_fwd.hpp contains almost all the code and Application.hpp includes Application_fwd.hpp and Assets.hpp before defining the Application::Application function template (just like you would define a function in a *.cpp file).
In Assets.hpp, you can simply use Application_fwd.hpp as long as you do not use the constructor. If you also use the Application constructor in Assets.hpp, things become a bit more complicated in that you need to very carefully consider all possible inclusion scenarios (i.e., what happens exactly every time one of your headers is included by themselves or a user) to make sure that it resolves in the order that you need it to without the guards causing trouble.
You can see it in action here

Getting around issues with templates inside Dll in C++?

Background:
I currently have a game engine project structured in visual studio so that my 'Engine' is compiled into a dll for another project 'Game' to consume. The idea being I can swap out different game projects and still use the same engine dll code. Within my engine code I'm creating my own framework for which all other engine code will use. This will help to separate my implementation from the rest of my code and make modification easier if need be.
Since all my framework code with be used within the dll itself and not within 'Game' I thought I could implement templates. However, I still receive the 'undefined symbol' error anytime I try and implement templates with the Engine framework.
Issue:
Is there a way to get around the 'undefined symbol' errors for templates from the linker within my dll without having to explicitly define every type my template will consume (ex. class template MyClass<int>, class template MyClass<float>, etc.)? If not, are there any suggestions on different ways I could implement my engine and different game projects to still keep things flexible? Thanks for any input.
P.S. I don't want to have to explicitly define all types a templated class could use since that would get rather large if I wanted to create say my own vector template class (as I would have to define A LOT of different classes).
Template intantiations are generated at compile time, so if you don't want to individually declare all possible instantiations then you must move all template definitions to be included with the header file.
One common way of doing this is for each class to have all of the template definitions in an inline file e.g a .inl or .cxx file, and then to include that inline file at the end of the corresponding header file.
For example, for a class Foo with a single templated function:
Contents of Foo.hpp:
class Foo
{
template <typename T>
void bar();
};
#include "Foo.inl" // Include template definitions
Contents of Foo.inl:
template <typename T>
void Foo::bar()
{
// body
}
That way, whenever Foo::bar<T> is used with a new T then an a new template instantiation will be generated.
Templates are supposed to be inline code. Their code created at code generation step when compiler encounters use of template, with code for that use case. In general attempt to force compiler to create class based on template is a fallacy , performance issue and inconvenience that opposes the purpose of having templates.
In general you need to declare object (variable) of specialized template to force compiler to generate one, if you have limited count of specialized variants< you need to declare them all. Even in that case compilers try avoid of creating new functions, unless they are virtual.
Most template libraries out there fully declare code of methods in headers, and may have no binary object files at all. Just do like mock_blatt said in comment, make declarations of templates in header and implementations of methods and friends in include file used from header.
"I don't want to have to explicitly define all types a templated class could use since that would get rather large"
What exactly do you expect the DLL to contain? Either it contains MyClass<float> or it doesn't. And the compiler would instantiate MyClass<T> for every type it knows, your DLL would be huge.

Do template class member function implementations always have to go in the header file in C++? [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 9 years ago.
Normally when I create a class, I create a header and a source for that class. I have heard that with a template class, you have to put the function implementation in the header. I tried doing it both ways, and got compilation errors the first way. The second way worked fine. However, I like to organize my code into headers and source files, so is it possible to put the function implementations into a source file? (Maybe it requires special compilation flags or syntax?) Or should I just keep em in the header?
Thanks!
Generally, all template code must be in a header file since the compiler needs to know the complete type at the point of instantiation.
As Aaron says below it is possible to put the implementation details in a .cpp-file in the specific case where you know on before hand all possible types the template will be instantiated with and explicitly instantiate it with those types. You'll then get a linker error if the template gets instantiated with another type somewhere in your code.
A quite common general solution to at least visually separate interface from implementation is to put all implementation in a .inc (or .tcc or .ipp)-file and include it at the end of the header file.
Note that the syntax for putting template class members outside the class-definition (whether you use the specific solution or the general) is slightly cumbersome. You'll need to write:
// in test.h
template <class A>
class Test
{
public:
void testFunction();
};
#include "test.inc"
// in test.inc
template <class A>
void Test<A>::testFunction()
{
// do something
}
(Edited: This is slightly more robust version which allows the implementation to be compiled into a separate .o file. The template should be explicitly instantiated at the end of the implementation cpp file. Perhaps this was only an issue for g++.)
You don't need to put the implementations in the header if you know which templates will be instantiated and can list them in the header implementation file. For example, if you know that you will only use int and std::string, then you can put this in the header file:
// test.h
template <class A>
class Test
{
public:
void f();
};
and put the implementation of f() into a normal test.cpp file:
// test.cpp
#include "test.h"
template <class A> void Test<A>::f() {
// implementation
}
template class Test<int>;
template class Test<string>;
Those last two lines explicitly instantiate the template classes. It is better to put this at the end of the implementation file, after it has seen the implementations of the member functions. Then you can compile it to a .o file g++ -c test.cpp. This test.o file will contain complete implementations of both Test<int> and Test<string> and can be linked without any difficulty in the rest of your application.
It works, but is it a good idea? It depends on context. In many cases, this works very well. If you are writing a template for 'internal' use in your project, then you know which templates will be instantiated and which will not. But if instead you're making something available to the public which must be very flexible, then you will need to include the implementations in the header file.
A tip: Even if it's for public consumption, take a look at the methods and see if there are any methods whose parameters and return type are independent of the template parameters. If so, you could place them into a Base class as (pure) virtual functions. This Base class doesn't use any templates and hence you may be able to use this Base* in much of your application (template <class A> class Test : public Base { ..., allowing you to limit the reach of the templated code throughout your application. I found this useful recently when much of the underlying behaviour and construction of a class depended on the template parameters, but the interface to the already-constructed object did not depend on the template parameters.
To answer the original question: no, the definitions of [member] function templates don't have to go into the header. However, the compiler needs to see the definition to instantiate the template. For templates instantiated with many different types you want the templates to be implicitly instantiated when they are used. This is e.g. the case for class templates like std::vector<...> and for function templates like std::copy(...). In this case it is almost certainly impractical to separate the template definition from its declaration although I personally put the definitions into a separate file included at the bottom of the header file.
For templates instantiated with only a few types like the stream classes or std::basic_string<...> it is often better to define the function templates in a separate header-like file which is only included in implementation files which explicitly instantiates them. This way the effort of instantiating the template is only spent once rather than in every translation unit using it. Especially for the stream classes this makes a huge difference (primarily for compile and link time but on some systems also for executable size). ... and I'm pretty sure hardly anybody has gone to the trouble of using the stream classes with different character types than char and wchar_t (hint: it is non-trivial to arrange for the various facets to be implemented and present in the std::locale). The technique of explicitly instantiating templates also works well if there is only a limited set of types with which the template is intended to work.
While it is technically the case that you can separate your implementation from your interface the syntax for templates gets so annoying to type repeatedly I would strongly recommend that you just hold your nose and put the implementation in your class until you get over the smell.
template <class X>
class klass_t {
public:
void f();
void g();
void h();
};
template <class X>
void klass_t<X>::f() { ... }
template <class X>
void klass_t<X>::g() { ... }
template <class X>
void klasS_t<X>::h() { ... }
Would have been:
template <class X>
class klass_t {
public:
void f() { ... }
void g() { ... }
void h() { ... }
};
Now imagine you want to add another template parameter (as in the following). Now you have to change the template argument lists in n places rather than just one.
template <class X, class Y>
class klass_t {
public:
void f();
void g();
void h();
};
Unless you have a good reason not to, it is a lot easier on your fingers to just put everything in the class.
Template implementations need to be known at compile-time. That means the implementations must be visible to the compiler. There's no way to go around this.
If you want to keep implementation details a secret, there's no way to do this. You can of course obfuscate your code, but that's not much of an impediment.
If your only concern is code organization, you can create a separate include file with the implementations and include it at the end of your main header (much as Andreas' suggestion).

(C++) where do I put all my templates?

I have different classes all arranged in a hierarchy.
To reduce the amount of code, I started creating template functions. The base class will use the template functions and some of the derived classes will also use the same functions. Where am I suppose to put all of these templates so I don't get undefined reference issues like I have been? Should I put all the definitions in a header file and then just include that header files in the .cpp part of the class that call the functions. will that work? As of right now, all of my classes(class.cpp, class.h) compile fine, but everything blows up during the linking. I tried to put all the templates in a namespace and then include that namespace in the implementation of all my classes but that doesn't seem to work. My question is, how would you go about making a separate entity that just holds templated functions that any class can use on it's data members?
The definitions of template functions and template classes belong in header files, not .cpp files.
This is because the compiler essentially has to generate a brand new function for each set of template parameters that's used in the file that #includes the header. If the template function were defined in a .cpp file, then all of the appropriate versions of these functions would have to be generated without knowing what the calling code looks like, and that's basically impossible. (You do get duplicate definitions of template functions this way, but the linker removes those and makes sure there's only one copy if each template instantiation in the final binary.)
I see a lot of people confused by this thing... templates are not types.
They become types when instantiated.
For this reason members of templates must stay in the same data unit you are going to use them.
If you template is generic and you want to use it in all your code, just put everything in header files.
Now, if you don't like (and i would understand that) that you show declarations and definitions and implementation all in the same file, you can split templates in two different files.
For example, "list.h" with your declaration and "list.inc" with your implementation.
To make it work, you have to include both.

How do I force a particular instance of a C++ template to instantiate?

See title. I have a template. I want to force a particular instance of a template to instantiate. How do I do this?
More specifically, can you force an abstract template class to instantiate?
I might elaborate as I have the same question. In my case I am building a library, some of the template implementations are large and include lots of stuff, but are only generated for a couple of types. I want to compile them in the library and export all the methods, but not include the header with the code everywhere.
ie:
template<class T>
OS_EXPORT_DECL class MyTmpl
{
T *item1;
public:
inline T *simpleGetT() { return(item1); } /* small inline code in here */ }
T *doSomeReallyBigMergeStuff(T *b); // note only declaration here
};
// *** implementation source file only seen inside library
template<class T>
MyTmpl<T>::doSomeReallyBigMergeStuff(T *b)
{
... a really big method, but don't want to duplicate it,
so it is a template ...
}
I could of course reference all the methods inside the library which would force them to compile and export but the desire isn't to add un-needed code to the library like the argument formatting for the items and the code to call them etc.
????? specifically I am building the library for several versions of MSC and GCC and intel compilers.
What you also can try is explicit instantiation:
template class vector<int>; // class
template int& vector<int>::operator[](int); // member
template int convert<int,double>(double); // function
You can't force generic templates to instantiate, the compiler can only generate code if the type is completely known.
Forcing an instantiation is done by providing all types explicitly:
template class std::vector<int>;
Comeaus template FAQ covers the related issues in some detail.
You can force instantiation by using the template with the desired parameter. For example you could define a function using all the required methods:
void force_int_instance() {
Abstract<int> *a;
a->some_method();
a->some_other_method(1, 2, 3);
}
You don't need to actually call that function anywhere, so it's not a problem that the pointer is not initialized. But the compiler has to assume that the function might be called from another object file, so it has to instantiate the template.
If I understand your question correctly, you have a template class, and you want to force the compiler to generate the code for use with some specific type. For example, you may want to ensure the code for std::vector<int> exists in your program.
The best way to ensure this is to simply construct an instance of the class:
void EnsureInstantiation()
{
std::vector<int> intvector;
std::vector<boo> boolvector;
/// etc.
}
The trick is that you don't even have to call EnsureInstantiation anywhere in your code. Just make sure it's not static or else the compiler may optimize it out.
abstract class cannot be instantiated.you probably want to do something along the lines of:
Abstract *a = new Implementation(...);
To force template instantiation, call template with template parameters:
std::max<int>(...);
std::pair<int, string>(...);
I'm going to answer what I think you meant, not what you said.
I am guessing the issue is one of two things. The first is that you have code in a template that's not getting compiled when you compile the template file itself, which can be very annoying. That can be fixed in your compiler settings.
The other is you want to have something special for a particular type, perhaps to debug it. That is called explicit instanciation but does not really instanciate anything just makes sure it's always defined after that point.
http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/topic/com.ibm.vacpp6m.doc/language/ref/clrc16explicit_instantiation.htm