On 9 Feb 2007 18:04:38 -0800, "(e-mail address removed)"
aaragon wrote:
Hi everyone,
I've been writing some code and so far I have all the code written in
the .h files in order to avoid the linker errors. I'm using templates.
I wanted to move the implementations to the .cpp files. After some
reading, I found that the only way to do this is to add the actual
template instantiations in the .cpp file. But, how do you do that if
you're not working with built-in types? For example, a template class
might be,
template
<
class Objective,
class StoragePolicy,
int k
class ClassA {
...
// declarations and definitions
...
}
How do I separate this into .cpp and .h files if I Objective and
StoragePolicy are defined by the user of the code?
Short answer: you don't.
In this example,
StoragePolicy is something that I could define (let's say
std::vector), but Objective is an object that the user provides. Is
there a way to get around this? I read also something about using the
"export" keyword but it doesn't seem to work with gnu g++.
The export keyword is meant for this purpose, however, most compilers don't
support it.
Any help will be appreciated.
Your options include:
a) leave the implementation code in the header files. This is common
practice.
b) use a compiler that supports "export". This is not common and will render
you code less portable.
Best
Kai-Uwe Bux
Thanks for your reply. I'll go with option a) for now. Best regards.
aaragon,
Although this isn't removing it from #included headers, this is a good
way to separate the implementation from definition in files.
/////foo.hh
#ifndef FOO_HH
#define FOO_HH
template< typename TYPE >
void
foo( TYPE val ) ;
#include "foo.tcc"
#endif
////foo.tcc
#include <iostream>
template< typename TYPE >
void
foo( TYPE val )
{
std::cout << val << std::endl ;
}
////main.cc
#include "foo.hh"
int
main( int argc, char* argv[] )
{
foo( 1 ) ;
}
///End of example.
HTH,
Paul Davis
I would even suggest:
// export_support_begin.hh
#if defined(EXPORT)
#undef EXPORT
#if defined(EXPORT_KEYWORD_SUPPORT)
#define EXPORT export
#else
#define EXPORT
#endif
// export_support_end.hh
#undef EXPORT
// foo.hh
#ifndef FOO_HH
#define FOO_HH
#include "export_support_begin.hh"
EXPORT template< typename TYPE >
void
foo( TYPE val ) ;
#if !defined(EXPORT_KEYWORD_SUPPORT)
#include "foo.tcc"
#endif
#include "export_support_end.hh"
#endif
// foo.tcc
#include <iostream>
#include "foo.hh"
#include "export_support_begin.hh"
EXPORT template< typename TYPE >
void
foo( TYPE val )
{
std::cout << val << std::endl ;
}
#include "export_support_end.hh"
// main.cc
#include "foo.hh"
int
main( int argc, char* argv[] )
{
foo( 1 ) ;
}
That way you can define EXPORT_KEYWORD_SUPPORT on compilers that support the
export keyword (notably Comeau and other compilers that use the EDG front
end).
It is safe to compile foo.tcc even on a noncompliant compiler.
-dr
I dunno. That seems like an awful lot of work for rather little pay
off. I'm not entirely certain about how the export keyword works, but
I imagine all this would save is the redundant compilation of a
multiple templates with the same type parameters.
Thought this was an interesting topic I haven't read enough about so I
googled around a bit and found a two articles about export. One for
and one against.
Against:
http://std.dkuug.dk/JTC1/SC22/WG21/docs/papers/2003/n1426.pdf
For:
http://www.comeaucomputing.com/iso/promises.html
Personally, I really don't see the motivation for a compiler to
support the feature other than to be fully standards conformant. The
article that was for keeping and requiring export did little to
convince me that export was a Good Thing (TM). In general the argument
seemed to be built on arguments that had little to do with the
theoretical aspects of why export is good and should be kept, instead
focusing on the fact that so much has already been put into it and its
not the only hard feature to implement.
The fact that this feature is so prohibitive to implement that major
compiler vendors aren't supporting it says something to me. I mean,
these people write *compilers* for a living. Although anecdotal and
trivial, how many features have made major compilers balk at
supporting them due to the prohibitively complex nature? I'd imagine
thats a fairly short list.
From what I've seen, all the 'odd' rules (e.g. koenig lookup) that
make up C++ have a very sound theoretical reason behind them. I
haven't found a good reason for supporting export other than the
original topic of separating template implementation from definition.
As always though, if someone can show me an example that will
absolutely not work without export I'd be happy to change my tune.
But until then, it seems like a waste of effort for compiler
developers.
Paul Davis