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.
Related
When we have a templated class (or function) that has a non-type template parameter, how are the versions generated by the compiler? Surely it doesn't create a version for every possible value of N
Suppose something like std::array<T,N> ?
I am trying to write my own templated function with a size_t template parameter, and I am trying to figure out whether/how I need to explicitly instantiate versions I will use
(I have split the program across different translation units)
I have a templated function which is something like
template <size_t N>
std::bitset<N> f(std::bitset<N> A){}
I put the declaration into a header file and definition into a .cpp file. It doesn't generate the correct version. So I tried to explicitly instantiate it like
template std::bitset<10> f<10>(std::bitset<10> A);
but I get the error that "error: explicit instantiation of .... but no definition available"
Neither the standard library nor you need to explicitly instantiate any template specialization, whether it has non-type template parameters or not.
Any specialization of the template which is used by the user in a way that requires a definition for the specialization to exist will cause it to automatically be implicitly instantiated if a definition for the entity which is instantiated is available. The condition should normally always be fulfilled since it is standard practice to place definitions of templated entities into the header file along with their initial declaration, so that they are accessible in all translation units using them.
So std::array<T,N> will be implicitly instantiated for all pairs of types T and values N which are actually used by the translation unit.
The only situation where explicit instantiation is required is if you intent to separate the definitions of template members into a single translation unit instead of the header file where they would be available for all translation units to implicitly instantiate. But you can only do that in the first place if you know all possible values for the template parameters, and you would then need to explicitly instantiate all of them, which for most non-type template parameters is not feasible.
Aside from that explicit instantiation may be used as an optimization of compilation time by avoiding implicitly instantiating template specializations in every translation unit where they are used. That makes sense only for specializations which you know will be often used. For example some standard library implementations apply it to std::string, which is the specialization std::basic_string<char>. It doesn't really make sense to apply it to e.g. std::array.
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.
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.
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.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why should the implementation and the declaration of a template class be in the same header file?
e.g when defining a template class why do the implementations of the class methods need to be in the header? Why can't they be in a implementation file (cpp/cxx)?
A template class is not a class, it's a template that can be used to create a class. When you instantiate such a class, e.g. MyTemplate<int>, the compiler creates the class on the spot. In order to create it, it has to see all the templated member functions (so that it can use the templates to create actual member functions such as MyTemplate<int>::foo() ), and therefore these templated member functions must be in the header.
If the members are not in the header, the compiler will simply assume that they exist somewhere else and just create actual function declarations from the templated function declarations, and this gives you linker errors.
The "export" keyword is supposed to fix this, but few compilers support it (I only know of Comeau).
You can also explicitly instantiate MyTemplate<int> - then the compiler will create actual member functions for MyTemplate<int> when it compiles the cpp files containing the MyTemplate member function definition templates.
They need to be visible for the compiler when they are instantiated. That basically means that if you are publishing the template in a header, the definitions have to be visible by all translation units that include that header if you depend on implicit instantiation.
They need not be defined in the header if you are going to explicitly instantiate the templates, but this is in most cases not a good idea.
As to the reason, it basically boils down to the fact that templates are not compiled when the compiler parses the definition, but rather when they are instantiated, and then they are compiled for the particular instantiation type.
If your compiler supports export, then it doesn't. Only EDG-based compilers support export, and it's going to be removed from C++0x because of that.
Non-exported templates require that the compiler can see the full template definition, in order to instantiate it for the particular types you supply as arguments. For example:
template<typename T>
struct X {
T t;
X(int i): t(i) {}
};
Now, when you write X<float>(5) in some translation unit, the compiler as part of compiling that translation unit must check that the constructor of X is type-correct, generate the code for it, and so on. Hence it must see the definition of X, so that it can permit X<float>(5) but forbid X<char*>(5).
The only sensible way to ensure that the compiler sees the same template definition in all translation units that use it, is to put the definition in a header file. As far as the standard is concerned, though, you're welcome to copy-and-paste it manually, or to define a template in a cpp file that is used only in that one translation unit.
export in effect tells the compiler that it must output a parsed form of the template definition into a special kind of object file. Then the linker performs template instantiation. With normal toolchains, the compiler is smart enough to perform template instantiation and the linker isn't. Bear in mind that template instantiation has to do pretty much everything that the compiler does beyond basic parsing.
They can be in a CPP file.
The problem arises from the fact that the compiler builds the code for a specific instantiation of a template class (eg std::vector< int >) on a per translation unit basis. The problem with defining the functions in a CPP file is that you will need to define every possible form in that CPP file (this is called template specialization).
So for that int vector exampled above you could define a function in a CPP file for the int case using specialization.
e.g
template<> void std::vector< int >::push_back( int& intVal )
Of course doing this can produce the advantage of optimisation for specific cases but it does give you an idea of just how much code bloat can be introduced by STL! At least all the functions aren't defined as inline as a certain compiler used to do ;)
That aspect of template is called the compilation model, not to be confused with the instantiation mechanism which was the subject of How does C++ link template instances.
The instantiation mechanism is the answer to the question "When is the instantiation generated?", the instantiation model is the answer to "Where the source are found?"
There are two standards compilation model:
inclusion, the one that you know, where the definition must be available,
separated, which allows to put the definition somewhere else with the help of the keyword export. That one has been removed from the standard and won't be available in C++0X. One of the raison for removal was that it wasn't widely implemented (only one implementation).
See C++ Templates, The Complete Guide by David Vandevoorde and Nicolai Josuttis or http://www.bourguet.org/v2/cpplang/export.pdf for more information, the separated compilation model being the subject of that later paper.