When would you use template explicit instantiation? - c++

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.

Related

How template class resolve member methods

I used to do what suggested here https://isocpp.org/wiki/faq/templates#separate-template-fn-defn-from-decl to separate template header and implementations. We basically explicitly instantiate the desired template at the end of .cc file so that the compilation unit contains enough information for the linker to work with.
I recently learnt that we only need to explicitly instantiate a class constructor to be able to create an instance. For example,
// .h file
template<typename T>
class A {
public:
A(T& t) : t_(t) {};
void PublicMethod();
private:
void PrivateMethod();
T& t_;
};
// .cc file
template<typename T>
void A<T>::PublicMethod() { PrivateMethod; return;}
template<typename T>
void A<T>::PrivateMethod() {
// Do some work.
return;
}
// Here I only instantiate the constructor and public interface.
template A::A(int);
template void A<int>::PublicMethod();
// In main, I can do following.
int main() {
A<int> a(2);
a.PublicMethod();
}
The part I am not clear is:
if I instantiate the public method, does it automatically instantiate all relevant private methods as well automatically?
No, if you explicitly instantiate a member (including a constructor), then only the definition for that member will be explicitly instantiated.
The explicit instantiation may cause implicit instantiation of other members of the class, but that isn't enough to use these members in a different translation unit. If you do not intent to use the private members in a different translation unit though, then it would be sufficient to explicitly instantiate the public/protected member functions.
If you want to explicitly instantiate all class members, you should explicitly instantiate the class template specialization itself:
template class A<int>;
template A::A(int);
This is not correct. Your constructor expects a reference, so it should be int& instead of int. Furthermore A is the template, not a specialization of it. You must specify a specialization:
template A<int>::A(int);

Can splitting template specializations between multiple files lead to ODR violations?

I wrote a parser class that contains base functionality for other, type specific parsers. For example, it contains a function to create an enum value from a string.
I didn't want the base class to contain information about the specific types, so I've implemented it as a template and used a trait to avoid including type specific headers:
// ParserBase.h
#include "EnumTrait.h"
template<typename EnumT>
EnumT parseEnum(std::string str)
{
return traits::EnumTrait<EnumT>::fromString(str);
}
The EnumTrait template is defined like so:
// EnumTrait.h
namespace traits
{
template<typename T>
struct EnumTrait
{
static_assert(sizeof(T) == -1, "Specialization not found");
};
} // namespace traits
Now, in each header where my enums are defined, there is also a specialization for this template. For example:
// Enum_A.h
#include "EnumTrait.h"
namespace A
{
enum class Enum_A
{
A
};
Enum_A fromString(std::string) {return Enum_A::A;}
} // namespace A
namespace traits
{
template<>
struct EnumTrait<A::Enum_A>
{
static std::string fromString(std::string str){ return A::fromString(str); }
};
// namespace traits
Headers for other enums look similar.
The usage of the base function:
// Enum_AParser.cpp
#include "ParserBase.h"
#include "Enum_A.h"
// ...
Enum_A foo = parseEnum<Enum_A>(bar);
// ...
My concern is: can this (does it) lead to ODR violations (or some other problems)?
It's impossible to use the trait with Enum_A and not have the specialization for it available, as they are defined in the same header.
But is it ok to not have every template specialization available in every TU where the template is used (for example Enum_A will not be available in the Enum_BParser)?
One thing I've noticed while thinking about this is that it is legal to create our own specializations of templates available in the standard library, so maybe it is ok after all?
I am using C++17, if that changes anything.
Looks OK to me. It is not required that every specialization be visible in every translation unit. It is only required that the specialization be declared before every use of the template that would otherwise trigger an implicit instantiation.
[temp.expl.spec]/7 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...

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

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.

Redeclaration error for a templated function

I have a setup where a templated function is inheriting another templated function.
template <typename DataType>
class ClassBase
{
virtual void InitModel(const cv::Mat& data) {};
}
template <typename DataType>
class ClassDerived : public ClassBase<DataType>
{
void InitModel(const cv::Mat& data) {};
}
Now I try to implement two specializations and one general templating for InitModel in ClassDerived in an implementation file
template<>
void ClassDerived<float>::InitModel(const cv::Mat& data)
{
// initialize some things
}
template<>
void ClassDervied<cv::Vec3b>::InitModel(const cv::Mat& data)
{
// initialize some things
}
template<typename DataType>
void ClassDerived<DataType>::InitModel(const cv::Mat& data)
{
// initialize some things
}
Before I wrote this, I did not have any specializations and it was working fine.
As soon as I added specialization, I get an error saying there was a redeclaration of the specification function. The weird part is that the redeclaration points out to the same line no. in the same file.
Since it was working fine before specialization, I expect the file isn't being read twice.
So, why would such an error start popping up as soon as the specializations are added ?
The error is :
/other/workspace/perception/perception_kit/object_detection/include/perception_kit/object_detection/grimson_GMM_templated_impl.tpp:129:
multiple definition of
`perception_kit::GrimsonGMMGen::InitModel(cv::Mat const&)'
CMakeFiles/test_obj.dir/src/object_detection_templated_test_platform.cpp.o:/other/workspace/perception/perception_kit/object_detection/include/perception_kit/object_detection/grimson_GMM_templated_impl.tpp:129:
first defined here
Is the problem because I am trying to derive a templated class or something else ?
Now I understand that for some, it might be a trivial problem but I have spent considerable time before I posted it here.
The base class is in BaseClass.h (its implemented as an abstract class)
The derived class declaration is in DerivedClass.h
The derived class declaration is in DerivedClass.tpp and is included in DerivedClass.h
You already defined the base template code inline in the header (with an empty body) so you can't redefine it again later. I suspect that's the source of your problem here, NOT the specializations.
You need to declare that you have specializations for those types. Otherwise, when the compiler in a different translation unit instantiates the template it will generate code for the member functions based on the primary template. When you try to link those generated functions with your specializations the linker will see multiple definitions of the specializations.
// Header
template <typename T>
struct test {
void f() {}
};
template <>
void test<int>::f(); // Declare the specialization
// Implementation (cpp, not included by client code)
template <>
void test<int>::f() { ... }
Note that function specializations are no longer templates, but regular functions. If different translation units include the definition of the function, then they will generate the code in multiple translation units. If you want to do that, then you can skip the declaration of the specialization and provide the definition directly, but you will need to make it inline:
// Implementation (if in header/included by user code)
template <>
inline void test<int>::f() { ... }

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.