A template class is a multitude of possible classes, so I was asking me: the preprocessor directives
#ifndef MY_CLASS
#define MY_CLASS
template<typename T>
class My_Class
{};
#endif
are necessaries?
The include guards prevent repeated inclusion of the same file. You need them to prevent a translation unit that would contain the following definitions, which are illegal:
template <typename T> class My_Class { };
template <typename T> class My_Class { };
// Error: redefinition of ‘class Foo<T>’
Repeat inclusion is very easy to occur. For example, consider a case where you include A and B, and A already includes B for some undocumented reason. You may not be entitled to omit B from your explicit includes, but neither should A be required to not include it. Only by using include guards (or some equivalent mechanism) can you make such a file structure possible.
In a nutshell: You can have repeated declarations, but only one definition within one translation unit.
Counter example: The following is legal:
template <typename T> class Foo;
template <typename T> class Foo;
template <typename T> class Foo;
template <typename T> class Foo;
template <typename T> class Foo { };
int main() {}
The macros are probably used as "include guards", preventing multiple-declarations errors if the header happens to be included multiple times. So yes, they are "as necessary" as for everything else: if you can be sure that the header won't ever be included multiple times you could leave them out, but on the other hand, they are not really adding to file sizes or compilation times.
Related
I split a generic class into a header and implementation file as follows.
Test.h:
#ifndef MY_DESCRIPTIVE_GUARD_NAME
#define MY_DESCRIPTIVE_GUARD_NAME
template<typename T>
class MyClass
{
T myObj;
public:
MyClass(T& obj);
void set(T& obj);
T get();
}
#include "Test.tpp"
#endif
Test.tpp:
template<typename T>
MyClass<T>::MyClass(T& obj) {
// implementation
}
// etc.
But as I add more methods to MyClass, I keep having to write the same boilerplate:
template<typename T> return-type MyClass<T>::method_name
With dozens of methods (not to mention if I include more template parameters), I'm writing a lot of repeated code. Should I use a macro? Suck it up? Or is there a feature in the language that allows me to package multiple method implementations in one unit, almost as if they were defined in the header file?
There has been a lot questions about different behavior between gcc and clang. However i did not find the solution for my problem yet.
I use templates and i want to spread the definition and implementation of the class. I read about it (a lot) i am aware of the different possibilities. I choose the specific declaration, which templates i want to support. With:
template class Temp<char>;
template class Temp<double>;
I choose which templates i support, which actually works, if i put those lines at the end of the template.cc file. However with gcc i also can write it in the header file. Clang does not support it, i get linking errors.
But why? What is wrong with the declaration of used templates in the header file???
This is my toy example:
template.hh
#pragma once
#include <iostream>
template<typename T>
class Temp
{
public:
Temp(T data);
virtual ~Temp (){};
void print();
private:
T data_;
};
//Only gcc can support this
//template class Temp<char>;
//template class Temp<double>
template.cc
#include "template.hh"
template<typename T>
Temp<T>::Temp(T data): data_(data)
{
}
template<typename T>
void Temp<T>::print()
{
std::cout << data_ << " " << sizeof(data_) << std::endl;
}
//Delete those, if it is used in header
template class Temp<char>;
template class Temp<double>;
test.cc
#include "template.hh"
int main(int argc, char *argv[])
{
Temp<char> temp = Temp<char>('c');
temp.print();
Temp<double> temp2 = Temp<double>(1.0);
temp2.print();
return 0;
}
Desired output:
c 1
1 8
Explicit template instantiation belongs in the ".cc" implementation file, not the header. If you want to declare it in the header, you can do so using extern:
extern template class Temp<char>;
extern template class Temp<double>;
This will avoid the multiply-defined symbols that you are probably experiencing with Clang otherwise.
It may be that GCC supports explicit instantiation in the header file, but this does not mean it is correct C++, only that GCC is being liberal in this case. Don't rely on that.
An explicit instantiation of a function template is a definition. Explicit instantiation of a class template is a short-hand for instantiating all [non-template] member functions of the class template. Having multiple definitions of an entity in C++ results in a violation of the ODR-rule (One Definition Rules). Violations of the ODR-rule do not need to be diagnosed.
As a result, explicit instantiations of template belong into a ".cc" file. If you want to declare that a template will be explicitly instantiated in some translation unit, you can use extern template declarations, e.g.:
template <typename> void f();
template <typename> class F { /*...*/ };
extern template void f<int>();
extern template class F<int>();
extern template declarations allow templates to be defined in the header but inhibit implicit instantiation. Instead, the extern template declaration promises that there will be one translation unit providing an explicit instantiation.
Is it proper to define your class outside of the pound defines for a class or do they go inside the pound defines? Examples of what I am asking can be seen below.
#ifndef CLASS
#define CLASS
template <typename T>
Class
{
Class();
};
template <typename T>
Class::Class()
{
}
#endif
---Or--
#ifndef CLASS
#define CLASS
template <typename T>
Class
{
Class();
};
#endif
template <typename T>
Class::Class()
{
}
I would define it within the include guards (pound defines) to avoid multiply defined symbols. So for template classes, as in your example, I would always define it within the include guards since they always have to be defined in header files.
For other non-template classes I might define member functions in a source (.cpp) file, so this would obviously be outside the include guards.
As a footnote I'd also point out that for such a simple constructor I'd actually define it within the class declaration, or even not define it at all, but I'm guessing your actual code is a little more complex than the example given.
I have a class Foo which is used in a small standalone project. It has a class definition in Foo.h with the implementation for the class' member functions in an implementation file Foo.cpp.
First question - one of the member functions of class Foo is a template method Foo::doSomething(), is it correct that the implementation of this method should appear with the declaration of the function in Foo.h ?
The template parameter which Foo::doSomething() will be instantiated with is one of two Functor types - class CalcA and CalcB.
Should I:
(A) put the defintion and implementation of the two Functor classes all together in Foo.cpp (where they are actually used by the implementation of other Foo member functions to call Foo::doSomething).
(B) put the definition and implementation of the two Functor classes in Foo.h.
(C) should I put split the definition and implementation of the two Functors across Foo.h and Foo.cpp as would be done with an ordinary class?
General rule:
If foo::doSomething() is used outside foo.cpp (i.e. if it's public or protected, usually), it must go in the header.
If not, putting in in the cpp file is perfectly ok, and even a good idea (as it keeps the clutter away from the header file).
So, if the functors are only used in the cpp file, by all means put the template function there too. One can always refactor things later if this changes.
First you must understand templates mechanism. Templates are not compiled, they are instantiated when they are used and then their instantiation is compiled. So the compiler needs to have the full template definition in each module using the template function, in order to instantiate them first according to the parameters you've passed.
To solve your problem, there are three solutions but you'll see that they both lead to the same result.
Either you implement your whole templates in your header file inside the class definition (we use to suffix them with .hxx instead of .h in order to precise they're containing templates definitions):
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T& t) {
t.doSomething();
}
};
#endif
Or you can externalize the definition from the class, but still in the header file:
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T&);
};
template <class T>
void Foo::bar(const T& t) {
t.doSomething();
}
#endif
Finally, you can implement template methods bodies in an external file (prefixed with .cxx for the same reason). It will contain methods' bodies but won't include "Foo.hxx". Instead, it's "Foo.hxx" that will include "Foo.cxx" after the class definition. This way, when the compiler resolves the #include directive, it finds the whole template definition in the same module, allowing it to instantiate it:
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T&);
};
#include "Foo.cxx"
#endif
// Foo.cxx
template <class T>
void Foo::bar(const T& t) {
t.doSomething();
}
The choice between these 3 ways to implement templates is rather a matter of readability (and taste).
Second and third are equivalent in terms of generated code, but I'd rather not use the cxx file solution, because it often leads to stupid errors when you forget to invert the include.
Moreover, well-known C++ libraries like STL or Boost propose their code in header files only, which is a sign of good design. By using external definition inside headers, you clarify the definition of your class. You also prevent the compiler to automatically inline methods, which can sometimes lead to poor results according to Herb Sutter http://www.gotw.ca/gotw/033.htm
My default would be to put the definition for the member function templates right in the .h file, like this:
class Foo
{
public:
template<typename T> void DoSomething(T t);
};
// ... later...
template<typename T>
void Foo::DoSomething(T t)
{
// ...
}
If this is suboptimal for a particular case, then I'd take more heroic measures. Starting with #include-ing a .inc file with the definition at the end of the .h file, or possibly even doing explicit instantiations in the .cpp files where I needed the member function templates to be used.
The template method definition should indeed be in the header file of it the class it belongs to.
Like this:
class MyClass
{
template <typename T>
void foo(const T&)
{
// Definition
}
};
Or like this (note that the template method definition can be included from separate file after the class declaration)
class MyClass
{
template <typename T> void foo(const T&);
};
template <typename T>
void MyClass::foo(const T&)
{
// Definition
}
The rest is depends on the style you agreed on and your needs.
I would put the functor declaration (or even the definition if they are simple) into the header if I use them not only in Foo or if Foo has them as class member.
usually, if my #include chain gets circular, I solve it by replacing one of the #includes by a forward declaration and then move all the function implementations that depend on this type into the cpp file, where I #include the header instead.
But - in some situations it's bad to put function implementation into the cpp file - especially when dealing with templates or for inline functions.
Therefore - Are there other ways to deal with circular #include chains rather than using forward declarations?
thanks!
You should limit such circular dependencies because they make code difficult to understand and hard to work with.
That said, sometimes such dependencies are necessary. In those cases, you can declare all of the entities in a single header file, then after all of the declarations provided definitions for any function templates and inline functions. For example:
#ifndef MY_AWESOME_INCLUDE_GUARD
#define MY_AWESOME_INCLUDE_GUARD
template <typename> struct B;
template <typename T>
struct A
{
template <typename U>
void f(B<U>);
};
template <typename T>
struct B
{
template <typename U>
void f(A<U>);
};
template <typename T>
template <typename U>
void A<T>::f(B<U>) { }
template <typename T>
template <typename U>
void B<T>::f(A<U>) { }
#endif