From what I understand template classes and template functions (for the most part) must be declared and defined in the same header file. With that said:
Are there any other ways to achieve separate compilation of template files other than using particular compilers? If yes, what are those?
What, if any, are the drawbacks of having the declaration and definition in the same file?
What is considered best-practice when it comes to template declaration & definition?
How To Organize Template Source Code
Basically, you have the following options:
Make the template definition visible to compiler in the point of instantiation.
Instantiate the types you need explicitly in a separate compile unit, so that linker can find it.
Use keyword export (if available)
One of the drawbacks encountered by implementing templates in the .h files is that any time you make a small change to the implementation, all the code that uses the template must be recompiled. There's really no way around this aside from not using templates, or declaring & defining them in the CPP file where you use them.
You can implement templates in a seperate file, and then include that file from the .h file. Such as:
templ.h
template<class V> V foo(const V& rhs);
#include "templ.inc"
templ.inc
template<class V> V foo*const V& rhs)
{
// do something...
return val;
}
My personal preference is to implement templates right in the h file unless they become large, and then I'll break it up in to h and inc files.
Not really. The definition of the template must be available at compile time, since templates are instantiated depending on the template arguments you give them. This is why they must be placed in headers, so the compiler can have the code to write a new instantiation. You pretty much need a compiler with support for the export keyword.
People can see your code, if that's a drawback to you. It might also be less "neat" to some people, but I don't think that's an issue.
A further problem is the compile times every time you change the .h (especially if it is included in a lot of places)
Not really. There is the export keyword, but most compilers don't support this. The only mainstream one that I know of that does support this is the Comeau compiler.
If your template is part of a public API then you're exposing your code to the world. (most people don't consider this a problem, but some do. It depends on your business).
Put them both in the same header file.
Related
For some reason, it seems that C++ doesn't like it when you split a template class (i.e. a class declared as template <typename T> class Thing) into a .h and a .cpp file, like you would do with any other class.
Does that mean that when writing a template class, I should just write it all in the header file? What do C++ programmers do in these cases?
EDIT: I understand that there are alternatives to writing it all in the .h file. But what's the best option? Or what the most common option?
It is popular to split the definition of a template out into another file. It is so popular it may even be the most common practice, but I am not positive about that.
I think this is poor practice (as opposed to putting the definitions in the same header) for the following reasons.
My priorities when writing code are (most important first):
Correctness.
Run time performance.
Compile time performance.
Maintainability / Easy to read.
Easy to write.
As long as the template definition is in the same header, or in another file that the header includes, the number one priority Correctness is not impacted one way or the other.
The second priority Run time performance is not impacted in the least.
The third priority Compile time performance is negatively impacted by putting the definition in a separate file. By how much is debatable. But there is no way that a compiler can compile X amount of code and open/close two files, as fast as it can compile the exact same code while opening/closing only one file. A friend of mine who is an excellent compiler writer once told me that the slowest thing I could ask his compiler to do was to open a file. This was before we did as much compile-time computation as we do today, but still...
The fourth priority Maintainability / Easy to read is quite subjective. But in my opinion a separate file is a negative impact on this priority. When I'm reading code, it is typically easier for me to understand it if it is all in one file. And I really get annoyed when I have to go hunting for the file when its name or location is not obvious. And I get even more annoyed when the definition is split into many files. For my money, one file optimizes this priority.
The fifth priority Easy to write is also quite subjective. I don't see much advantage either way on this one. It is very slightly easier to put everything in one file. But it is certainly not difficult to create a new file. I give the "one file approach" a very slight advantage on this priority.
So in summary, out of my five priorities, the two most important, this decision makes absolutely no difference on, and separate files have small negative consequences for the 3 lower priorities. Of the 3 lower priorities, the most important of these, compile-time performance is objectively negatively impacted. The two lowest priorities are admittedly subjective as to whether or not they are positively or negatively impacted.
I see no benefit and a small cost to putting your template definitions in a separate header.
"Does that mean that when writing a template class, I should just write it all in the header file? What do C++ programmers do in these cases?"
What you can do (and is wide spread/popular practice), is separate implementation code out to special template implementation files, that will in turn be in íncluded by the template headers, containing the declarations.
The gain of this technique is considered little for most of the cases, though it has it's points, if you want to hide the implementation details and not spill header files to become large.
The point is not to have the template definition code, or specializations in separate translation units, such these can be seen directly by other translation units, including the template header file.
The common pattern is
MyTemplate.h
#if !defined(MYTEMPLATE_H_)
#define MYTEMPLATE_H_
namespace myspace {
template <typename T>
class MyTemplate {
public:
void foo(T value);
};
#include "MyTemplate.tcc"
}
#endif // MYTEMPLATE_H_
MyTemplate.tcc
// NOTE: There aren't header guards for this file intentionally!
template<typename T>
void MyTemplate<T>::foo(T value) {
// ...
}
Other popular extensions for template implementation files are .icc, .ipp, .impl. Just important, it shouldn't be .cpp, since most IDE's or build system frameworks will track this as translation unit, unless it's explicitly excluded (here's a sample why).
"So simply instead of the .cpp #includeing the header, the header #includes the .tpp (which contains the implementations)?"
Template classes work a bit differently regarding the ODR (one definition rule). Regular header files, that provide class declarations shouldn't contain implementations because the ODR would be violated when these are included from different translation units:
MyClass.h
class MyClass {
public:
void foo(int);
};
// Violates ODR if MyClass.h is included from different translation units (.cpp files)
void MyClass::foo(int param) {
}
The templated version
template<typename T>
class MyClass {
public:
void foo(T);
};
// Doesn't violate ODR if MyClass.h is included from different translation units
// (.cpp files), since the template parameter isn't instatiated here yet.
template<typename T>
void MyClass<T>::foo(T param) {
}
As soon one translation unit instantiated something like MyClass<int>, other translation units instatiating the same template signature, will use the 1st one seen.
The latter implementation part could be replaced with an #include "MyClass.impl" that contains that code, if you think it messes up readability or maintainability of your header file too much.
As a minor drawback of the #include "MyClass.tcc" technique, you should notice, that most of the popular IDE's handle syntax highlighting and intellisense poorly for these kind of template implementation files.
I'm maintaining a large library of template classes that perform algebraic computations based on either float or double type. Many of the classes have accessor methods (getters and setters) and other functions that run small amounts of code, therefore such functions need to be qualified as inline when the compiler locates their definitions. Other member functions, in contrast, contain sophisticated code and thus would better be called rather than inlined.
A substantial part of the function definitions are located in headers, actually in .inl files included by headers. But there are also many classes whose function definitions happily live in .cpp files by means of explicit instantiation for float and double, which is rather a good thing to do in case of a library (here explained why). And finally, there is a considerable number of classes whose function definitions are broken across .inl files (accessor methods) and .cpp files (constructors, destructors, and heavy computations), which makes them all pretty difficult to maintain.
I would have all my class implementations in .inl files only if I knew a reliable way to prevent some functions from being inlined, or in .cpp files if inline keyword could strongly suggest compiler to inline some of the functions, which, of course, it does not. I would really prefer all the function definitions in the library to reside in .cpp files, but since accessor methods are used extensively throughout the library, I have to make sure they are inlined whenever referenced, not called.
So, in this connection, my questions are:
Does it make any sense to mark the definition of a template function with inline in view of the fact that, as I've recently learnt here, it is going to be automatically qualified as inline by the compiler regardless of whether it's marked with inline or not?
And most importantly, since I would like to have the definitions of all the member functions of a template class gathered together in a single file, either it's .inl or .cpp (using explicit instantiation in case of .cpp), preferably still being able to hint the compiler (MSVC and GCC) which of the functions should be inlined and which shouldn't, sure if such thing is possible with template functions, how can I achieve this or, if there is really no way (I hope there is), what would be the most optimal compromise?
----------
EDIT1: I knew that inline keyword is just a suggestion to the compiler to inline a function.
EDIT2: I really do know. I like making suggestions to the compiler.
EDIT3: I still know. It's not what the question is about.
----------
In view of some new information, there is also third question that goes hand in hand with the second one.
3. If compilers are so smart these days that they can make better choices about which function should be inlined and which should be called and are capable of link-time code generation and link-time optimization, which effectively allows them looking into a .cpp-located function definition at link time to decide its fate about being inlined or called, then maybe a good solution would be simply moving all the definitions into respective .cpp files?
----------
So what's the conclusion?
First of all, I'm grateful to Daniel Trebbien and Jonathan Wakely for their structured and well-founded answers. Upvoted both but had to choose just one. None of the given answers, however, presented an acceptable solution to me, so the chosen answer happened to be the one that helped me slightly more than others in making the final decision, the details of which are explained next for anyone who's interested.
Well, since I've always been valuing the performance of code more than how much convenient it is to maintain and develop, it appears to me that the most acceptable compromise would be to move all the accessor methods and other lightweight member functions of each of the template classes into the .inl file included by the respective header, marking these functions with inline keyword in an attempt to provide the compiler with a good hint (or with a keyword for inline forcing), and move the rest of the functions into the respective .cpp file.
Having all member function definitions located in .cpp files would hinder inlining of lightweight functions while unleashing some problems with link-time optimization, as has been ascertained by Daniel Trebbien for MSVC (in an older stage of development) and by Jonathan Wakely for GCC (in its current stage of development). And having all function definitions located in headers (or .inl files) doesn't outweigh the summary benefit of having the implementation of each class sorted into .inl and .cpp files combined with a bonus side effect of this decision: it would ensure that only the code of primitive accessor methods is visible to a client of the library, while more juicy stuff is hidden in the binaries (ensuring this wasn't a major reason, however, but this plus was obvious for anyone who is familiar with software libraries). And any lightweight member function that doesn't need to be exposed by the include files of the library and is used privately by its class can have its definition in the .cpp file of the class, while its declaration/definition is spiced with inline to encourage the inline status of the function (don't know yet whether the keyword should be in both places or just one in this particular case).
In short: Put the template code in a header file. Use compiler-specific forceinline or noinline keywords if the optimizer fails to make good decisions about inlining.
You can and should put definitions of template members into header files. This ensures that the compiler has access to the definition at the point of use when it finds out what the actual template parameters are, and is able to perform implicit instantiaion.
The inline keyword has very little impact on templates, since template functions are already exempted from the single definition requirement (The One Definition Rule still requires that all definitions be the same). It is a hint to the compiler that the function should be inlined. And you can omit it as a hint to the compiler to not inline the function. So use it that way. But the optimizer will still look at other factors (function size) and make its own choice on inlining.
Some compilers have special keywords, like __attribute__(always_inline) or __declspec(noinline) to override the optimizer's choice.
Mostly, though, the compiler is smart enough not to inline "complex code that makes more sense as a function call". You shouldn't have to worry about it, just let the optimizer do its thing.
Portable inlining control isn't beneficial, because the trade-offs of inlining are very platform-specific. The optimizers should already be aware of those platform-specific tradeoffs, and if you do feel the need to override the compiler's choice, do so on a per-platform basis.
1. Does it make any sense to mark the definition of a template function with inline in view of the fact that, as I've recently learnt, it is going to be automatically qualified as inline by the compiler regardless of whether it's marked with inline or not? Is the behavior compiler-specific?
I think you are referring to the fact that a member function defined in its class definition is always an inline function. This is per the C++ Standard, and has been since the first publication:
9.3 Member functions
...
A member function may be defined (8.4) in its class definition, in which case it is an inline member function (7.1.2)
So, in the following example, template <typename FloatT> my_class<FloatT>::my_function() is always an inline function:
template <typename FloatT>
class my_class
{
public:
void my_function() // `inline` member function
{
//...
}
};
template <>
class my_class<double> // specialization for doubles
{
public:
void my_function() // `inline` member function
{
//...
}
};
However, by moving the definition of my_function() outside of the definition of template <typename FloatT> my_class<FloatT>, it is not automatically an inline function:
template <typename FloatT>
class my_class
{
public:
void my_function();
};
template <typename FloatT>
void my_class<FloatT>::my_function() // non-`inline` member function
{
//...
}
template <>
void my_class<double>::my_function() // non-`inline` member function
{
//...
}
In the latter example, it does make sense (as in, it's not redundant) to use the inline specifier with the definitions:
template <typename FloatT>
inline void my_class<FloatT>::my_function() // `inline` member function
{
//...
}
template <>
inline void my_class<double>::my_function() // `inline` member function
{
//...
}
2. And most importantly, since I would like to have the definitions of all the member functions of a template class gathered together in a single file, either it's .inl or .cpp (using explicit instantiation in case of .cpp), preferably still being able to hint the compiler (MSVC and GCC) which of the functions should be inlined and which shouldn't, sure if such thing is possible with template functions, how can I achieve this or, if there is really no way (I hope there is), what would be the most optimal compromise?
As you know, the compiler may elect to inline a function, whether or not it has the inline specifier; the inline specifier is just a hint.
There is no standard way to force inlining or prevent inlining; however, most C++ compilers support syntactic extensions for accomplishing just that. MSVC supports a __forceinline keyword to force inlining and #pragma auto_inline(off) to prevent it. G++ supports always_inline and noinline attributes for forcing and preventing inlining, respectively. You should refer to your compiler's documentation for details, including how to enable diagnostics when the compiler is unable to inline a function as requested.
If you use those compiler extensions, then you should be able to hint to the compiler whether a function is inlined or not.
In general, I recommend to have all "simple" member function definitions gathered together in a single file (usually the header), by which I mean, if the member function does not require very many more #includes above the set of #includes required to define the classes/templates. Sometimes, for example, a member function definition will require #include <algorithm>, but it is unlikely that the class definition requires <algorithm> to be included in order to be defined. Your compiler is able to skip over function definitions that it does not use, but the larger number of #includes can noticeably lengthen compile times, and it is unlikely that you will want to inline these non-"simple" functions anyway.
3. If compilers are so smart these days that they can make better choices about which function should be inlined and which should be called and are capable of link-time code generation and link-time optimization, which effectively allows them looking into a .cpp-located function definition at link time to decide its fate about being inlined or called, then maybe a good solution would be simply moving all the definitions into respective .cpp files?
If you place all of your function definitions into CPP files, then you will be relying on LTO for mostly all function inlining. This may not be what you want for the following reasons:
At least with MSVC's LTCG, you give up the ability to force inlining (See inline, __inline, __forceinline.)
If the CPP files are linked to a shared library, then programs linking with the shared libraries will not benefit from LTO inlining of library functions. This is because the compiler intermediate language (IL)—the input to LTO—has been discarded and is not available in the DLL or SO.
If Under The Hood: Link-time Code Generation is still correct, "calls to functions in static libraries can't be optimized".
The linker would be performing all inlining, which might be a lot slower than having the compiler perform some inlining at compile time.
The compiler's LTO implementation might have bugs that cause it to not inline certain functions.
Use of LTO might impose certain limitations on projects using your library. For example, according to Under The Hood: Link-time Code Generation, "precompiled headers and LTCG are incompatible". The /LTCG (Link-time Code Generation) MSDN page has other notes, such as "/LTCG is not valid for use with /INCREMENTAL".
If you keep the likely-to-be-inlined function definitions in the header files, then you could use both compiler inlining and LTO. On the other hand, moving all function definitions into CPP files will restrict compiler inlining to only within the translation units.
I don't know where you learnt that, but templates are not "automatically qualified as inline by the compiler regardless of whether it's marked with inline or not". Templates and inline functions both have what is sometimes called "vague linkage" meaning their definitions can be present in multiple objects without error and the linker will use one of the definitions and discard the others. But the fact templates and inline functions both have vague linkage doesn't mean templates are automatically inline. Lions and tigers are both big cats but that doesn't mean lions are tigers.
Unless you know all the instantiations you are using in advance you can't always use explicit instantiation e.g. if you're writing a template library for others to use then you can't provide all the explicit instantiations, so you must define the template in .h (or .inl) files that the user of the code can #include. If you do know all the instantiations in advance then using explicit instantiations in .cpp files has the advantage of improving compilation time, because the compiler only instantiates the templates once in the file containing the explicit instantiations, not in every file that uses them. But that has nothing to do with inlining. For a function to be inlined its definition must be visible to the code calling it, so if you only define function templates (or member functions of class templates) in a .cpp file then they can't be inlined anywhere except in that file. If you define them in a .cpp file and do qualify them as inline then you might cause problems trying to call them from other files, which can't see the inline keyword (if a function is declared inline in one translation unit it must be declared inline in all translation units in which it appears, [dcl.fct.spec]/4.)
For what it's worth, I don't generally bother using .inl files, I just define templates directly in .h files, which gives one less file to deal with. Everything's in one place, and it just works, all files that use the templates can see the definitions and choose to inline them if desired. You can still use explicit instantiations in that case too, to improve compilation time and reduce object file size, without sacrificing inlining opportunites.
Why would that be better than just defining your template code in headers, where it belongs? What exactly are you trying to achieve? If it's fewer files, put the template code in headers, that will always work, the compiler can choose to inline everything without needing LTO, and you only have one file per class template (and you can still use explicit instantiation to improve compilation times). If you're trying to move all your code into .cpp files (which I think you're focusing on too much) then go ahead and do it. I think it's a bad idea, and will probably cause problems (link-time optimisation still has issues with the only compiler I've tried using it with, and certainly won't make compilation any faster) but if that's what you want, do whatever floats your boat.
It seems like your questions revolve around a misunderstanding here:
I would have all my class implementations in .inl files only if I knew a reliable way to prevent some functions from being inlined,
If all your template definitions are in header files you don't need "a reliable way to prevent some functions from being inlined" ... as I said above, templates are not automatially inline just because they're in headers, and if they're too large to inline the compiler won't inline them. First problem solved. Secondly:
or in .cpp files if inline keyword could strongly suggest compiler to inline some of the functions, which, of course, it does not, especially if a function marked with inline is located in a .cpp file.
As I said above, a function marked inline in a .cpp file is ill-formed unless it's also marked inline in the header, and never used in any other .cpp file. So doing this is just making life difficult and possibly causing linker errors. Why bother.
Again, all signs point to just put your template definitions in headers. You can still use explicit instantiation (as GCC does for std::string, as mentioned in the post you link to) so you get the best of both worlds. The only thing it doesn't achieve is hiding the implementations from users of the templates, but it doesn't sound like that's your aim anyway, if it is then provide non-template function API, which can be implemented in terms of templates in a single .cpp file.
This is not a complete answer.
I read that clang and llvm are able to do very comprehensive link time optimization. This includes link time inlining! To enable this, compile with optimization level -O4 when using clang++. The object files will be llvm bytecode instead of machine code. This is what makes this possible. This feature should therefore allow you to put all of your definitions in the cpp files, knowing that they will still be inlined where necessary.
Btw, the length of a function body is not the only thing that determines whether it will be inlined. A lengthy function that is only called from one location can easily be inlined at that location.
If I define a function (maybe a class member function but not inlined) in a header file that is included by two different translation units I get a link error since that function is multiply defined. Not so with templates since they are not compilable types until the compiler resolves a declaration of an object of a templatized type. This made me realize I don't know where compiled template code resides and how it is linked since C++ does not just create multiple copies of code to define SomeTemplateClass. Any info would be appreciated.
Thanks!
There are 3 implementation schemes used by C++ compilers:
greedy instantiation, where the compiler generates an instantiation in each compilation unit that uses it, then the linker throws away all but one of them (this is not just a code-size optimization, it's required so that function addresses, static variables, and the like are unique). This is the most common model.
queried instantiation, where the compiler has a database of instantiations already done. When an instantiation is needed, the DB is checked and updated. The only compiler I know which uses this is Sun's, and it isn't used by default anymore.
iterated instantiation, where the instantiations are made by the linker (either directly or by assigning them to a compilation unit, which will then be recompiled). This is the model used by CFront -- i.e. historically it was the first one used -- and also by compilers using the EDG front-end (with some optimisations compared to CFront).
(See C++ Templates, The Complete Guide by David Vandevoorde and Nicolai Josuttis. Another online reference is http://www.bourguet.org/v2/cpplang/export.pdf, which is more concerned about the compilation model but still has descriptions of the instantiation mechanisms).
All template functions are implicitly inline. Just as methods defined in the class declaration are implicitly inline.
When I say implicitly inline I mean the more modern usage of the word. See my lengthy description here.
In short, inline, static, and extern are all sibling linkage directives. inline tells the linker to ignore duplicate definitions of a function. Generally this means the linker will pick one definition and use it for all compilation units. I don't know of any compilers that do or did leave all duplicate template code in the final executable.
Where are template instantiations stored?
They are stored in the same way in the same place as inline functions. The details of that are compiler specific.
This is implementation specific.
Some compilers will generate the same template instances over and over for each translation unit they are instantiated in and let the linker fold the duplicates.
Templates got a bad reputation for "code bloat" when linkers weren't yet up to that task. Nowadays this is probably undeserved. Some implementations will even fold different instantiations when they compile to the same target machine code. (Like f<A*>() and f<B*>(), as pointer types are just addresses in the generated machine code.)
Others will defer template compilation until link-time instead, and there might be still other ways to deal with this. As I said, it's up to the implementation.
These all have different advantages and disadvantages. Absent of a true module concept I doubt anyone will come up with the perfect scheme.
With export there used to be a requirement for compilers to pre-compile template code and instantiate at request. However, except for one vendor nobody implemented export for their compiler, and now it's removed.
It actually does create multiple copies. Those copies are special and don't violate the one-definition rule. Some linkers will come along, remove the copies, and relink the functions using them; not all do.
The compiler says it can't find the reference for the function when I do this:
// link.h
template <class T>
T *Link(T *&, T *(*)())
// link.cpp
template <class T>
T c:Link(T *&ChildNodeReference, T *(*ObjectCreator)()){
}
If I implement inside the class on the header it goes smoothly.
Please, I will work on the header until someone enlightens me about this.
There are somethings in C++ that are weirdly annoying. I know, there is a reason for this and etc. Even so, can't the compilers help you out about it -_-"
Templates are essentially semi-type-safe macros, hence the limitation.
Normal (non-template) functions can be compiled to native code residing object/library files, and then referenced with only a prototype available in the header, solely because there's only a single version of such a function.
With templates, C++ compiler has to compile each instantiation of the function separately. Obviously, it cannot do it "in advance", because the set of types for which you can instantiate the function is effectively unbounded (you can always define a new type in your code before calling the function). In fact, two instantiations of the same function template can be completely different. Consider this extreme case:
struct t1 {
template <int>
struct a {};
};
struct t2 {
enum { a = 123 };
};
enum { b = 456, c = 789 };
template <class T>
void foo() {
T::a<b>c;
}
Now if we call foo<t1>(), the statement inside it is a local variable declaration, because t1::a is a class template:
T::a<b> c;
But if we call foo<t2>(), the statement inside is an expression, because t2::a is an integral constant:
(T::a < b) > c;
This is just to show that compiler cannot meaningfully "compile" a template; it really has to mostly preserve the tokens.
Now, all that said, ISO C++ does actually provide the ability to separate declaration and definition of templates, so that they can be treated as normal functions, with declarations in .h files, and definitions in .cpp files. This is called "export templates", because you have to precede both declaration and definiton with keyword export:
// link.h
export template <class T>
T *Link(T *&, T *(*)());
// link.cpp
export template <class T>
T *Link(T *&ChildNodeReference, T *(*ObjectCreator)()) {
}
This is, however, a controversial feature of the Standard because of very high burden on implementation, and most popular implementations refuse to implement it; notably, g++, MSVC, and C++Builder do not implement it. The only compiler I know of that supports it is Comeau C++.
Programming non-template code or non-inlined functions in headers is a Bad Thing™. The reason you have cpp files is to prevent redefinition of the same function code more than once, amongst other things.
The difference with templates is that the compiler practically doesn't touch them until your code instantiates a specialisation of that template which is why they need to have their source inside the header.
When the compiler finds an instantiation of a template specialisation (say List<int>), it goes back to the included template code and compiles it with that specialisation, which is why you don't have issues with redefinition of function code.
What you don't seem to understand is that this doesn't apply to non-templated code. All non-template code is compiled as normal and thus CPP files are needed to only define the code once then link it all together.
If you define functions inside a header, your linker will not link the compiled translation units because they have defined the same function more than once.
Templated implementations (not only definitions) have to be available at compile time.
So, the full template code is normally put in the header file.
Template code must be in the header. Sorry, I completely missed that! (and I thought I'd been coding C++ for years :P)
You forgot the * for the return type. So implementation is not matching definition. Add it and it should work:
T *c:Link(T *&ChildNodeReference, T *(*ObjectCreator)())
{
}
Implementation must be too in the header file under the class definition in order to be available at compile time.
It used to be that to use a template class in C++, the implementations had to be in the header file or #included into the header file at the bottom.
I've not used C++ templates for a few years; I just started using them again and observed that this behavior seems to persist. Is this still the case? Or are the compilers smart enough now to have the implementation separate from the interface?
Technically they do not need to be in the header file.
An example of this usage is when you have a template class with a fixed set of versions (lets say for arguments sake char and wchar_t). Then you can put all the method delcarations into a source file and explicitly instanciate these two versions. This has the safety that others can not istanciate the template for types it was not meant to be used for.
// X.h
template<typename T>
class X
{
// DECLARATION ONLY OF STUFF
public:
X(T const& t);
private:
T m_t;
};
// X.cpp
#include "X.h"
// DEFINTION OF STUFF
template<typename T>
X<T>::X(T const& t)
:m_t(t)
{}
// INSTANCIATE The versions you want.
template class X<char>;
template class X<wchar_t>;
// Main.cpp
#include "X.h"
int main()
{
X<chat> x1('a');
X<wchar_t> x2(L'A');
// X<int> x3(5); // Uncomment for a linker failure.
}
Assuming people can't just directly include X.cpp (because it is not provided by the distribution) then others can not use X<int> or X<float> etc. But the abovr classes are fully defined.
I have also seen this technique used to reduce compilatio time. Because each compilation unit is not re-generating the same version of X we only get the defintion in one place (thus one compilation cost). The downsize to this is that you must manually instanciate each seprate version of X that you use.
To separate the implementation from the declaration the standard forces you to use the export keyword. As far as I know there's only one compiler that knows how to handle it: Comeau.
However, C++0x will include a mechanism that tells the compiler not to instantiate certain specializations automatically (extern templates). So, if you want to cut compilation time you will be able to do so by explicitly instantiating some specializations in one compilation unit and declaring them in the header as extern.
You are referring to exported templates (using the export keyword), which seem to be supported only by Comeau C++ (according to this section of the C++ FAQ Lite).
A common technique to keep the interface devoid of implementation code is to put the inline function definitions into a separate "implementation" header that can be included at the end of the declaration header.
Export is only support by the EDG frontend, comercially only available in the Comeau compiler as far as I know.
Export doesn't eliminate the need for source disclosure, nor does it reduce compile dependencies, while it requires a massive effort from compiler builders.
So Herb Sutter himself asked compiler builders to 'forget about' export. As the time investment needed would be better spend elsewhere... so I don't think export will ever be implemented by other compilers after they saw how long it took, and how little was gained.
The paper is called "Why we can't afford export", it's listed on Sutters blog but no pdf there (a quick google should turn it up though), it's six years old now, I suppose they all listened and never bothered :)
Many people use two header files (e.g. .hpp and .ipp), one with only the declaration, and one with the definitions, then it's simply a matter of including one in the other.
foo.hpp
#ifndef MY_TEMPLATES_HPP
#define MY_TEMPLATES_HPP
template< class T >
void foo(T & t);
#include "foo.ipp"
#endif
foo.ipp
#ifdef MY_TEMPLATES_IPP
nonsense here, that will generate compiler error
#else
#define MY_TEMPLATES_IPP
template< class T >
void foo(T & t) {
... // long function
}
#endif
This only gains some clarity of course, nothing really changes compared to simply inlining everything in one header file.
GCC goes through a lengthy collect stage unless you explicitly instantiate all templates. VC++ seems to cope, but I prefer to avoid this step anyway and in cases where I know how template is going to be used, which is usually the case for applications, not so much for libraries, I put template definitions into a separate file. This also makes code more readable by making declarations less cluttered with implementation details.