Does explicit template instantiation go in cpp or header file?
Assuming by "explicit template instantiation" you mean something like
template class Foo<int>; // explicit type instantiation
// or
template void Foo<int>(); // explicit function instantiation
then these must go in source files as they considered definitions and are consequently subject to the ODR.
I've always done it in a cpp file. In a header, it would violate the one definition rule, at least (in the usual case) when the header was included in more than one cpp file (though there are ways to avoid that, which can be useful under a few, specific circumstances).
Either one.
If you are declaring a specific instance, you might declare it in your cpp file. However, if you are declaring a class member or something that will be referenced from multiple cpp files, that would go in your header file.
Related
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.
I saw an interesting thing but couldn't understand why.
template<class dataType>
Class A
{
AFnc();
}
template<> A<int>::AFnc() { }
Using only specialized template generates an error saying multiple definition of the same function. And it says it was generated at the same place.
But if I add
template<class dataType>
A<dataType>::AFnc()
{
}
Then it gets rid of the error.
Why ? Could someone please explain this behavior.
(You need to clean up your syntax. I assume that the actual code does not have all those syntax errors.)
Explicit specialization of template function is no longer a template, since it does not depend on any template parameters anymore. From the point of view of One Definition Rule (ODR) it is an "ordinary" function. And, as an "ordinary" function, it has to be declared in header file and defined only once in some implementation file. You apparently defined your specialization in header file, which is what leads to ODR violation if the header file gets included into multiple translation units (e.g. your "multiple definition" errors).
In your example, template<> void A<int>::AFnc() (I added void as return type) is no longer a template. This means that this definition
template<> void A<int>::AFnc() { }
must be moved from the header file to some implementation file. Meanwhile, in the header file you have to keep a non-defining declaration for this function
template<> void A<int>::AFnc(); // <- note, no function body
to let the compiler know that such specialization exists.
In general, remember the simple rule: if your function template still depends on some unspecified template parameters, it is a true template and it has to be defined in header file. But once you "fix" all the parameters (by explicit specialization) it is no longer a template. It becomes an ordinary function that has to be declared in header file and defined only once in some implementation file.
P.S. The above applies to non-inline functions. Inline functions can be (and are usually supposed to be) defined in header files.
P.P.S. The same logic applies to explicit specializations of static data members of template classes.
I guess, you put explicit instantiation in a header file. Then its code is emitted in every translation unit that includes that file. Just move this code
template<> A<int>::AFnc() { }
to .cpp file and it will be emitted only once.
You dont get this error with template method because rules for implicit instantiation are different.
During compilation I get a "multiple definition" error, which refers to a template specialisation in a header file. Do I need to put the specialisations into the source file?
If it is functions you have specialized, you can either put them in the .cpp file, or make them inline in the header.
Like James points out, if you don't make the functions inline, you still have to declare the specializations in the header. Otherwise the compiler doesn't know it has to look for them elsewhere.
You can then put the implementations (definitions) in a .cpp file. Just like with other functions.
No, you don't need to put specializations in a separately compiled file, but, you need to beware that a specialized function template is just an ordinary function, because it's fully specialized.
As such, it can't be defined in multiple translation units unless it's declared inline.
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.