Should I include everything I need in a template class header file? - c++

I run into a dilemma when I am writing a generic toString-like template class, which gives a QString representative of common data structures that I use. I wish I can include minimal numbers of other header files in this header file (#include in .h or .c / .cpp?), but also wish to have it not rely on the order it is included (Header file order).
The basic code is like this:
// Some headers
template <typename T>
class PMsg
{
// Public routines
public:
static QString fromType();
static QString fromValue(T const &val);
}; // PMsg
// Inline definition of all methods in PMsg<T>::fromValue
// Some specialisation
// To be continued...
And here comes the problems: container classes. Should I do the following to pulling all container headers to make it work:
// To the beginning
#include <QtCore/QList>
#include <QtCore/QVector>
// After PMsg<T>
template <typename T>
class PMsg<QList<T> >
{
// Public routines
public:
static QString fromType();
static QString fromValue(QList<T> const &val);
}; // PMsg
// Some definitions
template <typename T>
class PMsg<QVector<T> >
{
// Public routines
public:
static QString fromType();
static QString fromValue(QVector<T> const &val);
}; // PMsg
// Some definitions
Or to use macros to detect what headers are included as:
#if defined(QLIST_H)
template <typename T>
class PMsg<QList<T> >
{
// Public routines
public:
static QString fromType();
static QString fromValue(QList<T> const &val);
}; // PMsg
// Some definitions
#endif
#if defined(QVECTOR_H)
template <typename T>
class PMsg<QVector<T> >
{
// Public routines
public:
static QString fromType();
static QString fromValue(QVector<T> const &val);
}; // PMsg
// Some definitions
#endif
I might eventually include more than 20 different headers (including some non-Qt classes like those in Eigen), or I might rely on something Qt can change without telling downstream developers and ask my colleagues to include Qt headers before this header for sure.
I am also not sure how much effect on compiling time both ways would cause at this time (which probably should not be considered if I haven't get to this problem).
Is there any other better way to solve this or which way should I follow?
Sorry for the bad question title and thank you for your help.

Based on your description, you are providing a component with a customization point (PMsg<T>) to be used for components being added. It seems that you also want to have a certain set of already known components to take advantage of this customization. This leads to the following reasoning:
To use your component it is necessary to include a specific header (you didn't name it so I'll use "pmsg.h").
Newly created components can, and probably should, provide the relevant customization in their respective header, i.e., there is no need to customize these components in "pmsg.h".
Existing components (e.g. QVector<T>) are not aware of this customization and to seamlessly integrate with your component their customization needs to be declared in "pmsg.h". Without declaring the customization in "pmsg.h" all users would need to remember to also include the header declaring the customization in addition to the header of the existing component. Assuming there is a default implementation for the customization, that would not just have unexpected results but can easily lead to ODR violations when different translations units are inconsistent with respect to the headers they include.
For non-template components you can forward declare the component in "pmsg.h" to declare the customization and then implement it without any includes in the source file implementing the declarations from "pmsg.h". That is, for non-template components being customized there is no need to include the respective header with the declarations, a declaration suffices.
In general you can't safely forward-declare a class template (primarily because default arguments can only be declared for the first declaration). In addition, you'll probably need to provide a definition for the templated customization in the header "pmsg.h". That is, you'll need to include the declarations of all template classes you want/need to customize in your "pmsg.h".
tl;dr: if you want to provide customization for existing components you'll need to declare them in your header and to do so you'll need include their respective declarations, too.

Related

best practices: include .cpp file in main instead of .h file when using templates? [duplicate]

I have some template code that I would prefer to have stored in a CPP file instead of inline in the header. I know this can be done as long as you know which template types will be used. For example:
.h file
class foo
{
public:
template <typename T>
void do(const T& t);
};
.cpp file
template <typename T>
void foo::do(const T& t)
{
// Do something with t
}
template void foo::do<int>(const int&);
template void foo::do<std::string>(const std::string&);
Note the last two lines - the foo::do template function is only used with ints and std::strings, so those definitions mean the app will link.
My question is - is this a nasty hack or will this work with other compilers/linkers? I am only using this code with VS2008 at the moment but will be wanting to port to other environments.
The problem you describe can be solved by defining the template in the header, or via the approach you describe above.
I recommend reading the following points from the C++ FAQ Lite:
Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?
How can I avoid linker errors with my template functions?
How does the C++ keyword export help with template linker errors?
They go into a lot of detail about these (and other) template issues.
For others on this page wondering what the correct syntax is (as did I) for explicit template specialisation (or at least in VS2008), its the following...
In your .h file...
template<typename T>
class foo
{
public:
void bar(const T &t);
};
And in your .cpp file
template <class T>
void foo<T>::bar(const T &t)
{ }
// Explicit template instantiation
template class foo<int>;
Your example is correct but not very portable.
There is also a slightly cleaner syntax that can be used (as pointed out by #namespace-sid, among others).
However, suppose the templated class is part of some library that is to be shared...
Should other versions of the templated class be compiled?
Is the library maintainer supposed to anticipate all possible templated uses of the class?
An Alternate Approach
Add a third file that is the template implementation/instantiation file in your sources.
lib/foo.hpp - from library
#pragma once
template <typename T>
class foo {
public:
void bar(const T&);
};
lib/foo.cpp - compiling this file directly just wastes compilation time
// Include guard here, just in case
#pragma once
#include "foo.hpp"
template <typename T>
void foo::bar(const T& arg) {
// Do something with `arg`
}
foo.MyType.cpp - using the library, explicit template instantiation of foo<MyType>
// Consider adding "anti-guard" to make sure it's not included in other translation units
#if __INCLUDE_LEVEL__
#error "Don't include this file"
#endif
// Yes, we include the .cpp file
#include <lib/foo.cpp>
#include "MyType.hpp"
template class foo<MyType>;
Organize your implementations as desired:
All implementations in one file
Multiple implementation files, one for each type
An implementation file for each set of types
Why??
This setup should reduce compile times, especially for heavily used complicated templated code, because you're not recompiling the same header file in each
translation unit.
It also enables better detection of which code needs to be recompiled, by compilers and build scripts, reducing incremental build burden.
Usage Examples
foo.MyType.hpp - needs to know about foo<MyType>'s public interface but not .cpp sources
#pragma once
#include <lib/foo.hpp>
#include "MyType.hpp"
// Declare `temp`. Doesn't need to include `foo.cpp`
extern foo<MyType> temp;
examples.cpp - can reference local declaration but also doesn't recompile foo<MyType>
#include "foo.MyType.hpp"
MyType instance;
// Define `temp`. Doesn't need to include `foo.cpp`
foo<MyType> temp;
void example_1() {
// Use `temp`
temp.bar(instance);
}
void example_2() {
// Function local instance
foo<MyType> temp2;
// Use templated library function
temp2.bar(instance);
}
error.cpp - example that would work with pure header templates but doesn't here
#include <lib/foo.hpp>
// Causes compilation errors at link time since we never had the explicit instantiation:
// template class foo<int>;
// GCC linker gives an error: "undefined reference to `foo<int>::bar()'"
foo<int> nonExplicitlyInstantiatedTemplate;
void linkerError() {
nonExplicitlyInstantiatedTemplate.bar();
}
Note: Most compilers/linters/code helpers won't detect this as an error, since there is no error according to C++ standard.
But when you go to link this translation unit into a complete executable, the linker won't find a defined version of foo<int>.
Alternate approach from: https://stackoverflow.com/a/495056/4612476
This code is well-formed. You only have to pay attention that the definition of the template is visible at the point of instantiation. To quote the standard, § 14.7.2.4:
The definition of a non-exported function template, a non-exported member function template, or a non-exported member function or static data member of a class template shall be present in every translation unit in which it is explicitly instantiated.
This should work fine everywhere templates are supported. Explicit template instantiation is part of the C++ standard.
That is a standard way to define template functions. I think there are three methods I read for defining templates. Or probably 4. Each with pros and cons.
Define in class definition. I don't like this at all because I think class definitions are strictly for reference and should be easy to read. However it is much less tricky to define templates in class than outside. And not all template declarations are on the same level of complexity. This method also makes the template a true template.
Define the template in the same header, but outside of the class. This is my preferred way most of the times. It keeps your class definition tidy, the template remains a true template. It however requires full template naming which can be tricky. Also, your code is available to all. But if you need your code to be inline this is the only way. You can also accomplish this by creating a .INL file at the end of your class definitions.
Include the header.h and implementation.CPP into your main.CPP. I think that's how its done. You won't have to prepare any pre instantiations, it will behave like a true template. The problem I have with it is that it is not natural. We don't normally include and expect to include source files. I guess since you included the source file, the template functions can be inlined.
This last method, which was the posted way, is defining the templates in a source file, just like number 3; but instead of including the source file, we pre instantiate the templates to ones we will need. I have no problem with this method and it comes in handy sometimes. We have one big code, it cannot benefit from being inlined so just put it in a CPP file. And if we know common instantiations and we can predefine them. This saves us from writing basically the same thing 5, 10 times. This method has the benefit of keeping our code proprietary. But I don't recommend putting tiny, regularly used functions in CPP files. As this will reduce the performance of your library.
Note, I am not aware of the consequences of a bloated obj file.
Let's take one example, let's say for some reason you want to have a template class:
//test_template.h:
#pragma once
#include <cstdio>
template <class T>
class DemoT
{
public:
void test()
{
printf("ok\n");
}
};
template <>
void DemoT<int>::test()
{
printf("int test (int)\n");
}
template <>
void DemoT<bool>::test()
{
printf("int test (bool)\n");
}
If you compile this code with Visual Studio - it works out of box.
gcc will produce linker error (if same header file is used from multiple .cpp files):
error : multiple definition of `DemoT<int>::test()'; your.o: .../test_template.h:16: first defined here
It's possible to move implementation to .cpp file, but then you need to declare class like this -
//test_template.h:
#pragma once
#include <cstdio>
template <class T>
class DemoT
{
public:
void test()
{
printf("ok\n");
}
};
template <>
void DemoT<int>::test();
template <>
void DemoT<bool>::test();
// Instantiate parametrized template classes, implementation resides on .cpp side.
template class DemoT<bool>;
template class DemoT<int>;
And then .cpp will look like this:
//test_template.cpp:
#include "test_template.h"
template <>
void DemoT<int>::test()
{
printf("int test (int)\n");
}
template <>
void DemoT<bool>::test()
{
printf("int test (bool)\n");
}
Without two last lines in header file - gcc will work fine, but Visual studio will produce an error:
error LNK2019: unresolved external symbol "public: void __cdecl DemoT<int>::test(void)" (?test#?$DemoT#H##QEAAXXZ) referenced in function
template class syntax is optional in case if you want to expose function via .dll export, but this is applicable only for windows platform - so test_template.h could look like this:
//test_template.h:
#pragma once
#include <cstdio>
template <class T>
class DemoT
{
public:
void test()
{
printf("ok\n");
}
};
#ifdef _WIN32
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif
template <>
void DLL_EXPORT DemoT<int>::test();
template <>
void DLL_EXPORT DemoT<bool>::test();
with .cpp file from previous example.
This however gives more headache to linker, so it's recommended to use previous example if you don't export .dll function.
This is definitely not a nasty hack, but be aware of the fact that you will have to do it (the explicit template specialization) for every class/type you want to use with the given template. In case of MANY types requesting template instantiation there can be A LOT of lines in your .cpp file. To remedy this problem you can have a TemplateClassInst.cpp in every project you use so that you have greater control what types will be instantiated. Obviously this solution will not be perfect (aka silver bullet) as you might end up breaking the ODR :).
There is, in the latest standard, a keyword (export) that would help alleviate this issue, but it isn't implemented in any compiler that I'm aware of, other than Comeau.
See the FAQ-lite about this.
Yes, that's the standard way to do specializiation explicit instantiation. As you stated, you cannot instantiate this template with other types.
Edit: corrected based on comment.
None of above worked for me, so here is how y solved it, my class have only 1 method templated..
.h
class Model
{
template <class T>
void build(T* b, uint32_t number);
};
.cpp
#include "Model.h"
template <class T>
void Model::build(T* b, uint32_t number)
{
//implementation
}
void TemporaryFunction()
{
Model m;
m.build<B1>(new B1(),1);
m.build<B2>(new B2(), 1);
m.build<B3>(new B3(), 1);
}
this avoid linker errors, and no need to call TemporaryFunction at all
Time for an update! Create an inline (.inl, or probably any other) file and simply copy all your definitions in it. Be sure to add the template above each function (template <typename T, ...>). Now instead of including the header file in the inline file you do the opposite. Include the inline file after the declaration of your class (#include "file.inl").
I don't really know why no one has mentioned this. I see no immediate drawbacks.
There is nothing wrong with the example you have given. But i must say i believe it's not efficient to store function definitions in a cpp file. I only understand the need to separate the function's declaration and definition.
When used together with explicit class instantiation, the Boost Concept Check Library (BCCL) can help you generate template function code in cpp files.

C++ only implementation of template class

I do not have access to c++11 for this project.
I have a C++ class; lets call it Bar, it looks something like this:
Header FooBar.h:
#include "Fancy.h" // <--- Dependency
namespace Foo
{
template<typename T>
class Bar : public Fancy::FancyClass<T, ALLOCATER<HARD_CODED_VALUE>>
{
};
}
Cpp:
None
Fancy is a lib that is being statically linked into a dll. The problem is that when other projects want to use the dll they include "FooBar.h" it says that it cannot find "Fancy.h"
Basically I want projects that include the dll to be able to use this class without needing any additional libraries or headers.
My solution was to just put it in a cpp and have no header file. Unfortintly nothing can find it then? I have tried creating a blank header file that did not work either.
I tried to forward declare it in the header but to do that I need the .h to understand what FancyClass is. I have also tried
namespace Fancy
{
class FancyClass;
class ALLOCATER;
}
namespace Foo
{
template<typename T>
class Bar : public Fancy::FancyClass<T, ALLOCATER<HARD_CODED_VALUE>>;
}
in the header. But that causes many errors.
Short answer, you must include the header in your executable file in order to use the provided library.
Long(er) answer, the compiler needs to know the structure of the class defined in the library.
Imagine that there is a class called MyAwesomeClass that is part of a library you want to use in your executable. The compiler doesn't know anything about that class when you say MyAwesomeClass awesome;. How big is it? What methods can you call on it? Does it inherit from anything?
This information is contained in the header file where the class is declared.
class MyAwesomeClass
{
private:
std::string _name;
public:
MyAwesomeClass();
MyAwesomeClass(const std::string& name);
void print_name();
};
The implementation is defined in the DLL or static library, but when using the type MyAwesomeClass, the compiler needs to know at least its structure. Without including the header, the compiler will complain that it doesn't know what type MyAwesomeClass is (ie. undefined class errors).

about template code orginisation: where to put code that a template uses

I understand that template definitions should be put in the header file. Does this mean that all the definitions of the classes that the template uses (directly or indirectly) need to be put in the header files as well?
I have a template that has a lot of classes it depends on and thus have to put them all in the header file otherwise I will get "error LNK2019: unresolved external symbol ". Is there a better solution in terms of code organisation?
Example:
double inline MainFunction(double price, const Params& params)
{
Price<ModeEnum::NORMAL> pricer(price);
MethodOne<ModeEnum::NORMAL> methodOne;
return pricer.func(methodOne, params) ;
}
template<ModelEnum::Enum Mode>
struct Price
{
double price;
typedef double return_type;
Price(double price_) : price(price_){}
template<typename T> double func(const T& method, const Params& params) const
{
const typename T::PriceFactor factor(params);
return factor ..... ;
}
};
T::PriceFactor is actually class B that is a type definition defined in the tempalte MethodOne. Because of this, I have to put the constructor of class B and all (a lot) the functions and class that it uses in the header file.
The simple answer is this: all code needs to be visible to the compiler when the template gets instantiated. If the code isn't visible, the compiler won't do the instantiation and you'll need to provide an explicit instantiation. Whether an explicit instantiation is viable, depends on the nature of your template:
Templates which are applicable to many types, e.g., something like std::vector<T> probably want to be implemented entirely in a header. You may separate the declaration and the definition of function templates but there isn't much point in putting the parts into different files.
Templates which are applicable to few types, e.g., std::basic_ostream<cT> which is instantiated with char, wchar_t and maybe at some point with char16_t and char32_t probably want to be declared in a header and defined in another header which is not included automatically. Instead the header with the definitions is included only in special instantiation files where the class templates are explicitly instantiated.
Some templates give classes with different properties the same interface. That used to be the case with std::complex<T> which could be instantiated with float, double, and long double. For templates like these the header would only include the declarations and the definitions would go into a suitable translation unit.
One theme which is orthogonal to the above discussion is factoring out common parts, ideally into non-templates are into templates with fewer instantiations: it may very well be possible to take a very general interface but implement it in terms of a much more restrictive interface at the cost of somehow bridging the gap as part of the template implementation. In that case the "interesting" implementation may go into a source file rather than a header and the templates in the interface just adapt the passed in types to the actual implementation.
When mentioning above that code would be place into a source file this, obviously only applies to non-trivial code: simple forwarding functions probably should stay inline functions for performance reasons. However, these tend not to be the interesting function templates causing lots of dependencies.
For a more complete write-up on how to organize template code see this blog entry.
If its simple, I just put it all in one header:
//simple_template.h
#ifndef SIMPLE_TEMPLATE_H
#define SIMPLE_TEMPLATE_H
template <typename T>
class SomethingSimple
{
public:
T foo() { return T();}
};
#endif
If it is more complicated, I create an "inline header" (and use the naming convention from the google style guide) to get:
//complicated_template.h
#ifndef COMPLICATED_TEMPLATE_H
#define COMPLICATED_TEMPLATE_H
template <typename T>
class SomethingComplicated
{
public:
T foo();
};
#include "compilcated_template-inl.h"
#endif
//compilcated_template-inl.h
#ifndef COMPLICATED_TEMPLATE_INL_H
#define COMPLICATED_TEMPLATE_INL_H
#include "complicated_template.h"
template <typename T>
T SomethingComplicated<T>::foo() {/*lots of code here*/; return T();}
#endif
This way, complicated_template.h is pretty readable, but anyone who uses the template can just include that header. For example,
//uses_template.h
#ifndef USES_TEMPLATE_H
#define USES_TEMPLATE_H
#include "complicated_template.h"
class something_using_complicated
{
private:
SomethingComplicated<int> something_;
};
Note: if the classes that use the template are also template classes then you're stuck with a header only library. This is why BOOST is mostly headers.

C++ generic classes - separating interface and implementation

A very common coding practice is to separate the interface of a class from the implementation of its member functions through the use of .h and .cpp files on a per-class basis. So class Foo would be realised with a Foo.h header file and a corresponding Foo.cpp file.
This is often thrown out of the window in the special case of generic classes and instead header-only libraries are used to keep the compiler happy even though it does clutter the interface file with implementation details.
I've recently come accross some code written as follows. The .h file contains the interface and a #include to a .hpp file which contains the implementation of the generic member functions.
e.g. for a simple container of type T
Value.h
#ifndef VALUE_H
#define VALUE_H
template <typename T>
class Value
{
public:
Value(T value);
void set(T value);
T get() const;
private:
T data;
};
#include "Value.hpp"
#endif
and the corresponding Value.hpp
#ifndef VALUE_HPP
#define VALUE_HPP
template <typename T>
Value<T>::Value(T value) : data(value)
{
}
template <typename T>
void Value<T>::set(T value)
{
data = value;
}
template <typename T>
T Value<T>::get() const
{
return data;
}
#endif
This has the advantage of better separating interface and implementation coupled with the further benefit of actually compiling (in my limited testing).
My question is then are there any hidden pit-falls with adopting this convention?
Since you need to include both "value.h" and "value.hpp" in every file that uses the Value class, there is no benefit in compile time. But if you mean "it compiles" vs a solution where you put the implementation in a .cpp file, then yes, there is a benefit.
There is of course a benefit in that you can easily see the interface(s) provided by the class, without having the file cluttered up with a bunch of implementation code.
I'm not sure the naming convention of "value.h" and "value.hpp" is the 'best' choice. I think the "value.inl" is a better name for the second file.
No there are no special pitfalls with this solution. The .hpp file is just another header file which contains the definitions for the methods declared by the templated class. Since methods of templated classes needs to be defined in the header file this is a convenient method for separating the declaration from the definition. The extension .hpp shows that it is a hybrid of header and implementation file and is commonly used.

Cross source file template instantiation and use

I have a class with several template member functions that I would like to distribute among several source files to speed up compilation times. (The templates are implementation details and are not intended to be used outside the class, hence their definition in sources not headers.)
How would I go about splitting up these templates in such a way that I will not get linker errors? If I have source file A using a template defined in source file B, how do I make sure the appropriate instance of the template is constructed by the compiler?
I could not answer it better than C++ FAQ:
https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
Simply don't declare those template items as part of the class in the header file. Then, define your templates only in the source file. For example:
MyClass.hpp
class MyClass
{
public:
void SomePublicMethod() const;
};
MyClass.cpp
template<class T>
void SomethingWithT(T myVal)
{
// ...
}
void MyClass::SomePublicMethod() const
{
SomethingWithT(42);
}