Linking of template object files - different behavior with clang and gcc - c++

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.

Related

Placing C++ template definition for a class member function in CPP file with IMPLICIT instantiation instead of .H allowed?

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.

Cannot force instantiation of specialized template

In a static library I declared a template in Class.h then I specialized some methods in Class.cpp. I want to use this class in a project linking to this library.
I put the specialization in a .cpp file to avoid errors like "already declared" (???) end at the end of the same .cpp I declared the existence of the specialization once everything is known for this class. Here is the code:
Class.h
#ifndef __CLASS_H__
#define __CLASS_H__
template<class T>
class Class
{
public:
~Class(){}
Class(){}
//...
void method1()
{ /* unspecialized job here */ }
};
#endif
Class.cpp
#include "Class.h"
template<>
void Class<bool>::method1()
{
/* Specialized job for bool here */
}
// Declare that the class is specialized for bool
template class Class<bool>;
Now, in my project using the library, when I try to instantiate an object of class Class<bool>, it still use the unspecialized method.
What is the problem? Is the use of "template" at the end of the .cpp file correct?
I use gcc 4.8/4.9 on Kubuntu/Raspbian if it has an importance and I use C++11.
The template specializations
template<>
void Class<bool>::method1()
{
/* Specialized job for bool here */
}
// Declare that the class is specialized for bool
template class Class<bool>;
are seen only in Class.cpp. If Class<bool> is used anywhere else in your code, those specializations are not visible there. Hence, the generic class template is used to instantiate Class<bool>.
If you want the specializations to be visible to all the files where Class<bool> is used, move them to Class.h. At that point, Class.cpp won't be necessary any more unless it has code other than the lines above.
You need to use extern templates for the specialization to be effective.
In your cpp you have the specialization and this line:
template struct MyClass<bool>;
Then add to the header:
extern template struct MyClass<bool>;
Now the compiler will be told to not instantiate the template but to pick up the instantiated one in your cpp.

static member function inside class template specialization

I am struggling to access static member function defined inside class template.
In the header file TemplateTest.h I defined the primary class Template as:
#include<iostream>
template<class T, class U>
struct TemplateTest
{
public:
void static invoke();
/*{
std::cout << "Should not be called" << std::endl;
}*/
};
Then Source File TemplateTester.cpp I put a specialization:
#include "TemplateTest.h"
template<>
struct TemplateTest<int, bool>
{
static void invoke()
{
std::cout << "invoke<int, bool>" << std::endl;
}
};
template struct TemplateTest<int, bool>; //instantiate to resolve linker issue
I explicitly instantiated the class with so linker resolves correctly.
In the driver driver.cpp :
include "TemplateTest.h"
int main()
{
TemplateTest<int, bool>::invoke();
return 0;
}
When I compile the TemplateTest.cpp with g++ it generates the object file correctly but when I try to link it to the driver class it gives my linker error "undefined reference to `TemplateTest::invoke()"
I went through other related postings like this one but I am not trying access a function template.
Any clue is much appreciated.
You are right that the object file you create from TemplateTester.cpp will contain a symbol for the specialization you provided. This is the case because any explicit specialization causes the template to be instantiated, and it is doubly the case because you even added an explicit instantiation (which is actually unnecessary).
However, at the time when driver.cpp is compiled, the compiler does not know about the specialization, because you only include TemplateTester.h, and the specialization isn't mentioned there. So the compiler instantiates the template, of course not using the specialized definition, so you get your problem.
The Standard says (Italics by me):
(ยง14.7.3/6) If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required. An implicit instantiation is never generated for an explicit specialization that is declared but not defined. [...]
So you need to make both, the declaration and the definition of the specialization known to the compiler when it works on driver.cpp. The best way of doing this is by adding the entire specialization to TemplateTester.h.
Note, again, that an explicit instantiation is not actually required.
There are several problems :
you do not need to explicitly instantiate fully specialized template
if you want to put your static method in the header, then use inline. Otherwise you will get multiple instances and linker problems
template specializations you put in the header, and define methods in the source files
if you do not want something to be called in a template, you don't need to define it. You'll get compiler errors, and that means catching errors earlier.
// TemplateTest.h
#include<iostream>
template<class T, class U>
struct TemplateTest;
template<>
struct TemplateTest<int, bool>
{
inline static void invoke()
{
std::cout << "invoke<int, bool>" << std::endl;
}
};
// main.cpp
include "TemplateTest.h"
int main()
{
TemplateTest<int, bool>::invoke();
}
Another way is to change the header, and add the source file.
// TemplateTest.h
#include<iostream>
template<class T, class U>
struct TemplateTest;
template<>
struct TemplateTest<int, bool>
{
static void invoke();
};
// TemplateTest.cpp
#include "TemplateTest.h"
void TemplateTest<int, bool>::invoke()
{
std::cout << "invoke<int, bool>" << std::endl;
}

When would you use template explicit instantiation?

I've just been reading about template explicit instantiation:
template struct MyStruct<long>;
It was described as "quite rare", so under what circumstances would it be useful?
One of the use cases is to hide definitions from the end-user.
tpl.h:
template<typename T>
void func(); // Declaration
tpl.cpp:
template<typename T>
void func()
{
// Definition
}
template void func<int>(); // explicit instantiation for int
template void func<double>(); // explicit instantiation for double
main.cpp
#include "tpl.h"
int main()
{
func<double>(); // OK
func<int>(); // OK
// func<char>(); - Linking ERROR
}
Explicit instantiation is designed to optimize template libraries usage providing some of (mostly used) template instances in compiled binary form instead of source code form. This will reduce compile and link time for end-user applications. E.g. std::basic_string<char> and std::basic_string<wchar_t> can be explicitly instantiated in STL distribution avoid work on its instantiation in each translation unit.
Explicit instantiation is also useful when you want to encapsulate template implementation and you want this template to be used only with well-known set of types. In this case you can place only declarations of template functions (free or members) in header file (.h/.hpp) and define them in translation unit (.cpp).
Example:
// numeric_vector.h
//////////////////////////////////////////////////
template <typename T> class numeric_vector
{
...
void sort();
};
// numeric_vector.cpp
//////////////////////////////////////////////////
// We know that it shall be used with doubles and ints only,
// so we explicitly instantiate it for doubles and ints
template class numeric_vector<int>;
template class numeric_vector<double>;
// Note that you could instantiate only specific
// members you need (functions and static data), not entire class:
template void numeric_vector<float>::sort();
template <typename T> void numeric_vector<T>::sort()
{
// Implementation
...
}
Also explicit instantiation can be useful when you need instantiated type from template but inside some syntax construction that doesn't trigger instantiation itself, e.g. some compiler-specific meta-feature like __declspec(uuid) in Visual Studio.
Note the difference with another technique that could be used for implementation encapsulation - explicit specialization. With explicit specialization you must provide specific definition for each type to be specialized. With explicit instantiation you have single template definition.
Consider the same example with explicit specialization:
Example:
// numeric_vector.h
//////////////////////////////////////////////////
template <typename T> class numeric_vector
{
...
void sort();
};
template <> class numeric_vector<int>
{
...
void sort();
};
template <> class numeric_vector<double>
{
...
void sort();
};
// Specializing separate members is also allowed
template <> void numeric_vector<float>::sort();
// numeric_vector.cpp
//////////////////////////////////////////////////
void numeric_vector<int>::sort()
{
// Implementation for int
...
}
void numeric_vector<double>::sort()
{
// Implementation for double
...
}
void numeric_vector<float>::sort()
{
// Implementation for float
...
}
Having an explicit specialization allows you to hide the implementation, which, as you know, is usually impossible with templates.
I've seen this technique only once in a library that handled geometry, and they'd provide their own vector class.
So you could use
lib::Vector<MyShape>
with some basic functionality that lib::Vector provided, and basic implementations, and if you used it with their classes (some, not all)
lib::Vector<lib::Polygon>
you would use the explicit specialization. You wouldn't have access to the implementation, but I'm betting some hardcore optimizations were going on behind the scenes there.
If you really don't like defining template functions in header files, you can define the functions in a separate source file and use explicit template instantiation to instantiate all the versions you use. Then you only need a forward declarations in your header file instead of the complete definition.

Where to define C++ class member template function and functors that instantiate it?

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.