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

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.

Related

Should you split up implementation of member function templates and normal member functions?

If you have a class that contains both member function templates and normal member functions like so:
struct Foo
{
void normal();
template<typename T>
void templated();
};
With code maintainability in mind, what is the most efficient way of structuring the implementation of these member functions? With class templates, I usually put the implementation of member functions in a .inl file that I then include at the bottom of the header so that I still seperate the declaration code and the implementation code. I currently do the same with normal classes that contain template functions, but I'm unsure of where to implement the normal member functions. Putting them in a .cpp file obviously works, but it splits up the implementation of the member functions into two files, which isn't very intuitive. Functions and functions templates aren't neccessarily that different in the type of work they perform, so it's often not immediately clear if a given function implementation you're looking for is in the .inl file or the .cpp file, meaning you have to scan both of them.
Is the most long-term efficent solution to just put the normal function implementations into the .inl file as well, and just skip .cpp files entirely for classes that contain templates? Is there any advantage compile-wise that you miss out on if you don't put the normal functions in .cpp files?

How to avoid include files spreading due to template classes

Due to the implementation of a template class in a header file, I have to include the other includes used in the implementation of the class in the header file.
Because of that, each time I include my template class that bring all other the inclusions and so on.
This could bring to an eccessive spread of inclusion, or even unnecessary for the context.
So what's the best way to deal with this issue?
Edit: Since I've not explictely mentioned it, I'm not talking about cases where forward declaration could solve it like in a normal .h/.cpp separation, but when you have to include the header, and since you don't have the cpp, you are force to use it in .h
Edit 2: Let's say my template class has a function with a dependency with a third class library. Each class using my template class now has the same depency, or can access to that header which both I could not want to. Does it exists a way to avoid that?
Use forward declaration where ever appropriate instead of #include.
Header file should #include only the needed and rest should go in source file.

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.

How to make a template function in test.h use a static method inside test.cpp

Currently the template functions are inside the .cpp file, however these templates need to be defined in the header. However, when I move them in to the header, the templates have no access to the static methods inside the .cpp file. What changes do I need for this to work?
This is just a utility header and cpp, nothing to do with classes.
I would just go ahead and put declarations of all needed functions in a header file (and remove the static from their definitions). If you put them in namespace FunctionName_impl_detail or something like that, you're safe from name collisions. If you put comments near the declarations discouraging using them directly, you probably don't need to "hide" or "protect" them. But if you want to mostly prevent other code from using them, you can make them private, static members of some class which friends the template functions.
You should define the static method in the header.
Template classes have to be defined entirely in the header file because the compiler basically creates a new class for each template instantiation, so it has to have access to the full method implementation at compilation time.

Do I have to mention private methods in the header file of a class?

For now I do not use header files at all. Classes are each in a single .cpp file completely. But to save compile time I want to make use of header files now. My hope is that Visual Studio won't compile classes which weren't modified for debug builds then.
Is there a way to mention only public methods and members in the header file. In theory that would be enough information for the compiler. If another file, say main.cpp includes the class header there is no need for private methods and members, is it?
How can I use header files without retyping the names of private methods and members? The reasons for me to want so is coding productivity. When I want do add a small helper function to the class used by another method, I don't want to have to also add it's signature to the header file.
If another file, say main.cpp includes the class header there is no need for private methods and members, is it?
No, public methods and members aren't necessarily enough. For example, if another .cpp file were to try and create an instance of your class:
SomeClass instance;
the compiler will need to know, among other things, how much memory to allocate for SomeClass. For that it requires full knowledge of SomeClass's private data members.
The way you are framing the question makes it sound as if you were intent on fighting the language. I don't think that's a good way to go about it. I think the best way is to do things the way things are usually done in the language of your choice, and depart from that only when there is a specific, clearly understood need.
The way things are usually done in C++ is that the entire class declaration goes in the header file, and the definition is in some way split between the header file and the corresponding .cpp file. The exact split is determined by various technical considerations. For example, templates and inline functions normally have to appear in the header file. On the other hand, placing code in header files increases dependencies and potentially build times.
There are ways to address these issues. However, since this involves extra complexity, I'd argue that this should only be done if there is a clearly identifiable need.
I don't know of a way to do what you're asking, but there is another way to give some isolation. You might want to take a look at the pimpl idiom as it offers isolation about private information. It's a little bit of extra work, but it can be extremely useful, especially in large projects.
All function declarations should go in header files and all function definitions should go in cpp files. It's not good coding practice to put declarations inside the cpp files.
You could put definitions inside headers though, when you write templates or inline functions.
Once you declare the class in the header file, you have to declare all its methods and members inside the class' declaration in the header, given that your class is no longer declared in the cpp file.