How do I prevent implicit template instantiations for a specific template? - c++

I'd like to prevent all implicit template instantiations for a specific templated class in order to prevent it from being instantiated into every translation unit.
It looks like my options are:
Use -fno-implicit-templates on gcc's command line. This
suppresses all implicit template instantiations, and is not what I want. I only want to prevent it for a single template.
Use C++11 "extern template". But this only suppresses specific
explicit instantiations. I don't want to type out an "extern
template" line for every potential template parameter list this
template might be instantiated with.
So I need something in-between. It would be nice to have:
extern template class Foo; // suppress all implicit instantiations of Foo
(Note the lack of template parameter(s).) Any ideas?

you can use std::enable_if which does exactly this with the combination of std::is_same :
template <class T , typename = std::enable_if <!std::is_same<T,Foo>::value,T>::type >
class MyClass{
//...
};
now myClass won't be compiled for Foo type.

I would say that the answer to your question is using C++ new type traits to assert the instantiations in your constructor:
static_assert(std::is_same<TInstantiation, [your-predefined-type]> || std::is_same<TInstantiation, [your-predefined-type2]> /*And so on...*/, "Classname can not be instantiated using this type!");
It's all guaranteed to resolve at compile time :)

You can split the class like you would with a non-template class. Just put the declarations into a header and include that everywhere, and put the implementation into an .inl/.i file and include that only where you want your template to be instantiated. Alternatively, use compile time switches to do this with a single file - but you do have to separate declaration and implementation.

Related

What does the compiler do when you make a function template? [duplicate]

I'm reading a book about how templates work, and I'm having difficulty understanding this explanation of templates.
It says
When the compiler sees the definition of a template, it does not generate code. It generates code only when we instantiate a specific instance of the template. The fact that code is generated only when we use a template (and not when we define it) affects how we organize our source code and when errors are detected...To generate an instantiation, the compiler needs to have the code that defines a function template or class template member function. As a result, unlike non-template code, headers for templates typically include definitions as well as declarations.
What exactly does it mean by "generate code"? I don't understand what is different when you compile function templates or class templates compared to regular functions or classes.
The compiler generates the code for the specific types given in the template class instantiation.
If you have for instance a template class declaration as
template<typename T>
class Foo
{
public:
T& bar()
{
return subject;
}
private:
T subject;
};
as soon you have for example the following instantiations
Foo<int> fooInt;
Foo<double> fooDouble;
these will effectively generate the same linkable code as you would have defined classes like
class FooInt
{
public:
int& bar()
{
return subject;
}
private:
int subject;
}
and
class FooDouble
{
public:
double& bar()
{
return subject;
}
private:
double subject;
}
and instantiate the variables like
FooInt fooInt;
FooDouble fooDouble;
Regarding the point that template definitions (don't confuse with declarations regardless of templates) need to be seen with the header (included) files, it's pretty clear why:
The compiler can't generate this code without seeing the definition. It can refer to a matching instantiation that appeared first at linking stage though.
What does a non-template member function have that allows for it to
be defined outside of the header that a template function doesn't
have?
The declaration of a non-template class/member/function gives a predefined entry point for the linker. The definition can be drawn from a single implementation seen in a compiled object file (== .cpp == compilation unit).
In contrast the declaration of a templated class/member/function might be instantiated from arbitrary compilation units given the same or varying template parameters. The definition for these template parameters need's to be seen at least once. It can be either generic or specialized.
Note that you can specialize template implementations for particular types anyway (included with the header or at a specific compilation unit).
If you would provide a specialization for your template class in one of your compilation units, and don't use your template class with types other than specialized, that also should suffice for linking it all together.
I hope this sample helps clarifying what's the difference and efforts done from the compiler.
A template is a pattern for creating code. When the compiler sees the definition of a template it makes notes about that pattern. When it sees a use of that template it digs out its notes, figures out how to apply the pattern at the point where it's being used, and generates code according to the pattern.
What is the compiler suppose to do when it sees a template? Generate all the machine code for all possible data types - ints, doubles, float, strings, ... Could take a lot of time. Or just be a little lazy and generate the machine code for what it requires.
I guess the latter option is the better solution and gets the job done.
The main point here is that compiler does not treat a template definition until it meets a certain instance of the template. (Then it can proceed, I guess, like it have a usual class, which is a specific case of the template class, with fixed template parameters.)
The direct answer to your question is: Compiler generates machine code from users c++ code, I think this is wat is meant here by word "generate code".
The template declaration must be in header file because when compiler compiles some source, which use template it HAVE only header file (included in source with #include macro), but it NEED whole template definition. So logical conclusion is that template definition must be in header.
When you create a function and compile it, the compiler generates code for it. Many compilers will not generate code for static functions that are not used.
If you create a templated function and nothing uses the template (such as std::sort), the code for the function will not be generated.
Remember, templates are like stencils. The templates tell how to generate a class or function using the given template parameters. If the stencil is not used, nothing is generated.
Consider also that the compiler doesn't know how to implement or use the template until it sees all the template parameters resolved.
It won't straight away generate code. Only generates the class or template code when it comes across an instantiation of that template. That is, if you are actually creating an object of that template definition.
In essence, templates allow you abstract away from types. If you need two instantiations of the template class for example for an int and a double the compiler will literally create two of these classes for you when you need them. That is what makes templates so powerful.
Your C++ is read by the compiler and turned into assembly code, before being turned in machine code.
Templates are designed to allow generic programming. If your code doesn't use your template at all, the compiler won't generate the assembly code associated. The more data types you associate your template with in your program, the more assembly code it will generate.

Can I use `-fno-implicit-templates` feature only for one template?

Is it possible to forbid implicit instantiation, like -fno-implicit-templates does, but only for one template?
I have a problem with implicit instantiation of incomplete template, which causes compilation failure (part of implementation is hidden in source file, and I don't want to have it in other TUs). -fno-implicit-templates solves the problem, but at cost of problems with using STL and other templates.
You can try to use explicit template instantiation. Put explicit template instantiation declaration extern template class TemplateClass<ArgumentsSet>; (where ArgumentsSet is a TemplateClass arguments set for which you want to avoid implicit instantiation in your code) in your header file (you can put such directive for several arguments sets if you want). Also put explicit template instantiation definition template class TemplateClass<ArgumentsSet>; in your source file to explicitly instantiate TemplateClass for ArgumentsSet in this translation unit.

How does the compilation of templates work?

I'm reading a book about how templates work, and I'm having difficulty understanding this explanation of templates.
It says
When the compiler sees the definition of a template, it does not generate code. It generates code only when we instantiate a specific instance of the template. The fact that code is generated only when we use a template (and not when we define it) affects how we organize our source code and when errors are detected...To generate an instantiation, the compiler needs to have the code that defines a function template or class template member function. As a result, unlike non-template code, headers for templates typically include definitions as well as declarations.
What exactly does it mean by "generate code"? I don't understand what is different when you compile function templates or class templates compared to regular functions or classes.
The compiler generates the code for the specific types given in the template class instantiation.
If you have for instance a template class declaration as
template<typename T>
class Foo
{
public:
T& bar()
{
return subject;
}
private:
T subject;
};
as soon you have for example the following instantiations
Foo<int> fooInt;
Foo<double> fooDouble;
these will effectively generate the same linkable code as you would have defined classes like
class FooInt
{
public:
int& bar()
{
return subject;
}
private:
int subject;
}
and
class FooDouble
{
public:
double& bar()
{
return subject;
}
private:
double subject;
}
and instantiate the variables like
FooInt fooInt;
FooDouble fooDouble;
Regarding the point that template definitions (don't confuse with declarations regardless of templates) need to be seen with the header (included) files, it's pretty clear why:
The compiler can't generate this code without seeing the definition. It can refer to a matching instantiation that appeared first at linking stage though.
What does a non-template member function have that allows for it to
be defined outside of the header that a template function doesn't
have?
The declaration of a non-template class/member/function gives a predefined entry point for the linker. The definition can be drawn from a single implementation seen in a compiled object file (== .cpp == compilation unit).
In contrast the declaration of a templated class/member/function might be instantiated from arbitrary compilation units given the same or varying template parameters. The definition for these template parameters need's to be seen at least once. It can be either generic or specialized.
Note that you can specialize template implementations for particular types anyway (included with the header or at a specific compilation unit).
If you would provide a specialization for your template class in one of your compilation units, and don't use your template class with types other than specialized, that also should suffice for linking it all together.
I hope this sample helps clarifying what's the difference and efforts done from the compiler.
A template is a pattern for creating code. When the compiler sees the definition of a template it makes notes about that pattern. When it sees a use of that template it digs out its notes, figures out how to apply the pattern at the point where it's being used, and generates code according to the pattern.
What is the compiler suppose to do when it sees a template? Generate all the machine code for all possible data types - ints, doubles, float, strings, ... Could take a lot of time. Or just be a little lazy and generate the machine code for what it requires.
I guess the latter option is the better solution and gets the job done.
The main point here is that compiler does not treat a template definition until it meets a certain instance of the template. (Then it can proceed, I guess, like it have a usual class, which is a specific case of the template class, with fixed template parameters.)
The direct answer to your question is: Compiler generates machine code from users c++ code, I think this is wat is meant here by word "generate code".
The template declaration must be in header file because when compiler compiles some source, which use template it HAVE only header file (included in source with #include macro), but it NEED whole template definition. So logical conclusion is that template definition must be in header.
When you create a function and compile it, the compiler generates code for it. Many compilers will not generate code for static functions that are not used.
If you create a templated function and nothing uses the template (such as std::sort), the code for the function will not be generated.
Remember, templates are like stencils. The templates tell how to generate a class or function using the given template parameters. If the stencil is not used, nothing is generated.
Consider also that the compiler doesn't know how to implement or use the template until it sees all the template parameters resolved.
It won't straight away generate code. Only generates the class or template code when it comes across an instantiation of that template. That is, if you are actually creating an object of that template definition.
In essence, templates allow you abstract away from types. If you need two instantiations of the template class for example for an int and a double the compiler will literally create two of these classes for you when you need them. That is what makes templates so powerful.
Your C++ is read by the compiler and turned into assembly code, before being turned in machine code.
Templates are designed to allow generic programming. If your code doesn't use your template at all, the compiler won't generate the assembly code associated. The more data types you associate your template with in your program, the more assembly code it will generate.

Template function in non-template class - Division between H and CPP files

I was (and have been for a long time) under the impression that you had to fully define all template functions in your .h files to avoid multiple definition errors that occur due to the template compilation process (non C++11).
I was reading a co-worker's code, and he had a non-template class that had a template function declared in it, and he separated the function declaration from the function definition (declared in H, defined in CPP). It compiles and works fine to my surprise.
Is there a difference between how a template function in a non template class is compiled, and how a function in a template class is compiled? Can someone explain what that difference is or where I might be confused?
The interesting bit is how and when the template gets instantiated. If the instantiations can be found at link time, the template definition doesn't need to be visible in the header file.
Sometimes, explicit instantiations are cause like this:
header :
struct X {
// function template _declaration_
template <typename T> void test(const T&);
};
cpp:
#include "X.h"
// function template _definition_:
template <typename T>
void X::test(const T&)
{
}
// explicit function template _instantiation(s)_:
template X::test<int>(const int&);
template X::test<std::string>(const std::string&);
Using this sample, linking will succeed unless uninstantiated definitions of the template are used in other translation units
There is no difference between function templates defined in namespace or in class scope. It also doesn't matter whether is inside class template or not. What matter is that at some point in the project any used function template (whether member or non-member) is instantiated. Let's go over the different situations:
Unused function templates don't need to be instantiated and thus their implementation doesn't need to be visible to compiler at any point in time. This sounds boring but is important e.g. when using SFINAE approaches where class or function templates are declared but not defined.
Any function template which is defined where it is used will be instantiated by the compiler in a form which allows multiple definitions across different translation units: only one of the instantiations is retained. It is important that all the different definitions are merged because you could detect differences if you took the address of a function template or used a state variable inside the function template: there shall be only one of these for each instantiation.
The most interesting setup is where the definition of the function template is not seen when the function template is used: in this case the compiler cannot instantiate it. When the compiler sees a definition of the function template in a different translation unit it wouldn't know which template arguments to instantiate! A Catch 22? Well, you can always explicitly instantiate a template once. Having multiple explicit instantiations would create multiply defined symbols.
These are roughly the important options. There are often good reasons that you don't want to have the definition of a function template in the header. For example, you don't necessarily want to drag in dependencies you wouldn't have otherwise. Putting the definition of the function template somewhere else and explicitly instantiating it is a good thing. Also, you might want to reduce the compile time e.g. by avoiding to instantiate essentially the entire I/O stream and locale library in every translation unit using the stream. In C++ 2011 extern templates were introduced which allow the declaration that a particular template (either function or class template) is defined externally once for the entire program and there isn't any need to instantiate it in every header using particularly common template arguments.
For a longer version of what I just said, including examples have a look at a blog post
I wrote last weekend on this topic.

About C++ template and explicit declaration

I just spent about an 20 minutes trying to figure out why some template methods of mine passed compilation but not linkage.
Turns out I needed to explicitly declare my template method.
It was something of this kind :
class Test {
template<class Source> void Save(Source& obj);
};
Then I would use it like this somewhere :
Test t;
ClassDerivedFromInterface obj;
t.Save(obj);
It compiled fine but didn't link. Until I added :
template void Test::Save(ClassDerivedFromInterface);
I would like to understand in which case an explicit declaration is necessary.
Thanks
In a nutshell, you need to have the entire body (the definition) of a template function visible to the translation unit that instantiates the template. So when you say t.Save(obj);, that translation unit should have access to the definition of Save. Usually you achieve this by including the definitions of function templates in the header file itself.
The reason for this is that templates aren't ordinary code that gets compiled and can later be linked at will. Rather, templates are a code generation tool that generates the necessary code on demand - an automatic version of copy/paste followed by search-and-replace, if you will.
Therefore, the actual compilable code for your function Save(ClassDerivedFromInterface&) doesn't come into existence until you write that line. If only the declaration of the function template is visible, then the template only produces the declaration of the concrete function, but not its body, and so at link time you notice that the function is missing.
To recap, templates themselves cannot be compiled, it is only their concrete instances that can, and you have to pay attention to ensure that the concrete instances are always available when you instantiate them. Explicit instantiation as you have it works and allows you to package a few specific instances into a separate TU, but generally that's hard to maintain and not scalable, and there are other drawbacks to explicit instantiation that you avoid when you let the compiler instantiate implicitly. So usually it's best to package your entire definitions into the header file.
You will need to explicitly declare the template if the template source is not visible at the time of compilation. This link covers it pretty well, also an awesome site in general:
C++ FAQ 35.13
You need explicit declaration when your template definitions are not accesible from the code that is using them, consider the following:
template.h - template declarations
template.cpp - template definitions
main.cpp - template usage
template.cpp is not included in main.cpp and thus unreachable by the template user so you need explicit declarations.
But if your structure is:
template.h - template declarations and definitions
main.cpp - template usage
the template declarations are reachable by the template user so you don't need explicit declarations.
The compiler needs to know what types you're going to be using with your template. If you create a template class and then use it with, for example, int, char, and double, then the compiler will create methods for the template for those types. If you compile the template method in a separate compilation unit from where you use it, the compiler will not instantiate your template for the type you need. But if you explicitly instantiate the template, the compiler will create whatever you tell it to.