I have a template class definition that needs to be in the cpp file. Adopting from http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13, I did something like this:
// File "foo.cpp"
#include <iostream>
#include "foo.h"
template<typename T> void foo()
{
std::cout << "Here I am!\n";
}
template void foo<int>();
I instantiate the template from the .cpp file. However, I need different types like foo(string) etc and I realized that I could only instantiate it once. How could I fix it?
Thanks.
You should be able to instantiate foo for each type you need.
template void foo<int>();
template void foo<double>();
template void foo<std::string>();
This is somewhat onerous, which is the reason many libraries tend to provide template function implementations in header files, so that any instantiation can be available to any cpp file which includes the header.
The template specialization should be in a separate translation unit (.cpp file) and the template (generic) definition in a header file.
In the foo.h
add the definition
template <typename T> void foo ()
{
std::cout << "Here I am! << std::endl;
}
In the foo.cpp use it
foo <int> ()
foo <std::string> ();
Related
Given code like the following:
foo.cpp
#include"foo.h"
template <int X>
void bar::foo(){
cout << X << endl;
}
static void tea(){
bar().foo<1>();
bar().foo<2>();
bar().foo<3>();
}
foo.h
class bar {
public:
template <int X>
void foo();
};
main.cpp
...
bar().foo<1>();
bar().foo<2>();
bar().foo<3>();
...
Is such a pattern allowed in any version of C++?
Edit:
Why is this disallowed when explicit instantiation with template void bar::foo<1>() (and etc) would allow this to link correctly?
C++ compilers are not required to actually generate symbols for anything unless you force it with an extern declaration. They aggresively inline functions, which might remove all evidence of your instantiation. I tried out your example, and it linked with -O0, but not with -O3.
I have a class:
// A.h
class A
{
void foo();
template <class T> void bar( T someVar );
}
#include "A.tcpp"
When I build it, I get linker errors. However, if the whole class would be a template, then the above example would build perfectly fine. So my question is:
How do I stick to the pattern of having ALL definitions in the cpp file, when having template member functions as opposed to having a template class?
If you are going to split a a class that has template functions and non template functions into a header file and a tcpp file then you only put the template definitions in the tcpp file. The non template definitions still needs to go into a regular cpp file.
Putting the non template code in the tcpp file includes it back into the header file and then that means it gets defined in every translation unit it gets included into.
In this case that means you should have
// A.h
class A
{
void foo();
template <class T> void bar( T someVar );
}
#include "A.tcpp"
// A.tcpp
template <class T> void A::bar( T someVar ) { some code; }
// A.cpp
#include "A.h"
void A::foo() { some code; }
I found the solution, it is not as nice as I would like, but it will do in my case. We can insert the following line at the end of the tcpp file:
template void A::bar<int>( int );
// And so on, for all types that should be supported.
It is called function template instantiation.
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.
C++11 introduced a feature called 'extern template' which indicates that template instance exists in other translate unit.(Am I right?)
This(http://www.youtube.com/watch?v=3annCCTx35o) lecture also tells that if you specify extern template and don't include instantiation, the linker will produce error.(around 2:25 in the video)
So, I've tried to build next code:
#include <iostream>
template<class T>
struct Foo
{
static constexpr int type_size = sizeof(T);
};
extern template struct Foo<int>;
int main()
{
std::cout<< Foo<int>::type_size << std::endl;
return 0;
}
I expected the build will fail because this file does not contain explicit instantiation nor specialization, but gcc just builds it up the result runs well.
What am I missing? Or, am I misunderstanding something? Or, does not gcc support extern template well?
Update
I've tried a class with non-inline function, and extern template works as expected!
#include <iostream>
template<class T>
struct Foo
{
static void print(T t);
};
template<class T>
void Foo<T>::print(T t) { std::cout << t << std::endl; }
extern template struct Foo<int>;
// template struct Foo<int>;
int main()
{
Foo<int>::print(1);
return 0;
}
Above source is not built without the commented line.
Thank you all guys!
if you specify extern template and don't include instantiation, the linker will produce error.
No, not necessarily. There is only a problem if you actually use the template. You're using a compile-time constant defined as a static member of that template, but that is replaced by the constant's value at compile-time. And after that replacement, there is no longer any use of the template, so there is no need for a definition of the template.
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.