[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-devel
Subject:    Re: C++ template question.
From:       Andrew Sutton <asutton () cs ! kent ! edu>
Date:       2005-02-27 21:23:33
Message-ID: 200502271623.33981.asutton () cs ! kent ! edu
[Download RAW message or body]

On Sunday 27 February 2005 02:11 pm, Jonas Widarsson wrote:
> If you like to comment on something not related to KDE at all, read on.
> Someone granted a couple of months ago that I can ask some newbie questions
> on this list, so here comes one! ;)
>
> Skip to B if your'e in a hurry ... :)

> here's the error message:
> /usr/lib/gcc-lib/i586-pc-linux-gnu/3.3.2/include/g++-v3/bits/vector.tcc:244
>: undefined reference to `void OscillatorBase::fillBuffer<float>(float*,
> unsigned const&, int const&)'
>
> So I start wondering. Is my use of templates illegal?
> I mean, people talk about template functions and template classes.
> My OscillatorBase::fillBuffer() code is supposed to be a template function
> within an ordinary class. Is that a design error?
>
> Thanks.

here's the quick and dirty answer... because the templated implementation of 
your function is in the .cpp file, only the templated declaration is visible 
to files including the header - that's why the linker is telling you that you 
have an undefined reference. your other files are finding the declaration and 
compiling correctly, but they can't link because the _implementation_ has 
never been instantiated.

there are several ways to get around this. my favorite way is to inline the 
implementation within the class. for example:

// A.hxx
struct A
{
 // in-lined implementation
 template <class B> void foo(B *b)
 {
  std::cout << *b << std::endl;
 }
}

another way is to implement the method outside the class declaration, but 
inside the same header file.

// A.hxx
struct A
{
 // externally implemented method
 template <class B> void foo(B *b);
};

template <class B> void A::foo(B *b)
{
 std::cout << *b << std::endl;
}

a third and less popular methods is to move all of the externally implemented 
template methods of a class and #include them at the end of the .h file.

// A.hxx
struct A
{
 template <class B> void foo(B *b);
};

#include "A.txx" // note the extension difference

or something like that.

from what i've seen, experienced developers will use the first option for 
trivial methods (< ~10 lines maybe) and the second option for larger more 
complicated methods. if you're going to use the third option, i'd recommend 
writing down a very good reason for doing it. it's not exactly standard 
practice, but it is done every now and then. check out the bits/ directory in 
the GCC c++ stdlib include directory and look for .tcc files. anyways, i've 
never seen any written down rules as to which style is appropriate and when. 
maybe somebody should.

hope that help.

andrew sutton
asutton@cs.kent.edu
 
>> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic