Wednesday, 11 October 2017

c++ - Why can templates only be implemented in the header file?

itemprop="text">

Quote from href="http://books.google.com/books?id=n9VEG2Gp5pkC&pg=PA10&lpg=PA10&dq=%22The%20only%20portable%20way%20of%20using%20templates%20at%20the%20moment%20is%20to%20implement%20them%20in%20header%20files%20by%20using%20inline%20functions.%22&source=bl&ots=Ref8pl8dPX&sig=t4K5gvxtBblpcujNxodpwMfei8I&hl=en&ei=qkR6TvbiGojE0AHq4IzqAg&sa=X&oi=book_result&ct=result&resnum=3&ved=0CC8Q6AEwAg#v=onepage&q=%22The%20only%20portable%20way%20of%20using%20templates%20at%20the%20moment%20is%20to%20implement%20them%20in%20header%20files%20by%20using%20inline%20functions.%22&f=false"
rel="noreferrer">The C++ standard library: a tutorial and
handbook:





The only portable way of using templates at the moment is to implement them in
header files by using inline
functions.





Why
is this?



(Clarification: header files are not
the only portable solution. But they are the most convenient
portable solution.)


itemprop="text">
class="normal">Answer



It is
not necessary to put the implementation in the header file, see the
alternative solution at the end of this
answer.



Anyway, the reason your code is failing
is that, when instantiating a template, the compiler creates a new class with the given
template argument. For
example:



template            T>
struct Foo

{
T bar;
void
doSomething(T param) {/* do stuff using T */}
};

//
somewhere in a .cpp
Foo f;



When reading this
line, the compiler will create a new class (let's call it
FooInt), which is equivalent to the
following:




struct
FooInt
{
int bar;
void doSomething(int param) {/* do
stuff using int
*/}
}


Consequently,
the compiler needs to have access to the implementation of the methods, to instantiate
them with the template argument (in this case int). If these
implementations were not in the header, they wouldn't be accessible, and therefore the
compiler wouldn't be able to instantiate the
template.




A common solution to this
is to write the template declaration in a header file, then implement the class in an
implementation file (for example .tpp), and include this implementation file at the end
of the header.



//
Foo.h
template
struct Foo
{

void doSomething(T param);
};

#include
"Foo.tpp"


// Foo.tpp
template T>
void Foo::doSomething(T param)
{

//implementation
}


This
way, implementation is still separated from declaration, but is accessible to the
compiler.






Another
solution is to keep the implementation separated, and explicitly instantiate all the
template instances you'll need:



//
Foo.h

// no implementation
template
struct Foo { ...
};


//----------------------------------------

// Foo.cpp

// implementation of Foo's
methods

// explicit instantiations
template class
Foo;
template class Foo;
// You will only be
able to use Foo with int or
float



If my
explanation isn't clear enough, you can have a look at the href="https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl"
rel="noreferrer">C++ Super-FAQ on this subject.



No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print ...