2

Possible Duplicate:
Why can templates only be implemented in the header file?

I'm getting some errors in gcc and clang that I'm not familiar with. First off, here's the code in question.

WaypointTree.h:

class WaypointTree {

 private:
  Waypoint *head = nullptr;
  Waypoint *current = nullptr;
  template<class Function>
    void each_recur(Waypoint *current, Function f);

 public:
  template<class Function>
    void foreach(Function f);
  void add(Waypoint *wp, Waypoint *parent = nullptr);
  bool isLast(Waypoint *wp);
  Waypoint *next();
  Waypoint *getHead() { return head; }
  void reverse() {}
};

WaypointTree.cpp:

. . .

template<class Function>
void WaypointTree::foreach(Function f) {
  each_recur(head, f);
}

. . .

Flock.cpp:

. . .

_waypoints->foreach([] (Waypoint *wp) {
        glPushMatrix(); {
          glTranslatef(wp->getX(), wp->getY(), wp->getZ());
          glutSolidSphere(0.02, 5, 5);
        } glPopMatrix();
      });

. . .

With clang, I get the following warning:

lib/WaypointTree.h:17:7: warning: function 'WaypointTree::foreach<<lambda at lib/Flock.cpp:128:22> >' has internal linkage but is not defined
        void foreach(Function f);
             ^
lib/Flock.cpp:128:14: note: used here
        _waypoints->foreach([] (Waypoint *wp) {
                    ^

Followed by the following linker error:

lib/Flock.cpp:128: error: undefined reference to 'void WaypointTree::foreach<Flock::render(std::vector<Boid*, std::allocator<Boid*> >)::$_3>(Flock::render(std::vector<Boid*, std::all
ocator<Boid*> >)::$_3)'

With gcc I get only the following error :

lib/WaypointTree.h:17:7: error: ‘void WaypointTree::foreach(Function) [with Function = Flock::render(std::vector<Boid*>)::<lambda(Waypoint*)>]’, declared using local type ‘Flock::ren
der(std::vector<Boid*>)::<lambda(Waypoint*)>’, is used but never defined [-fpermissive]

I'm not really sure where to begin debugging this, but it seems to be related to the templates and the lambdas.

Community
  • 1
  • 1
gregghz
  • 3,925
  • 7
  • 40
  • 69
  • yes, it seems it is somewhat duplicated, now that answers have come in. However, the errors I was getting aren't mentioned in the other question. The other question presupposes that templates have to be implemented in the header file, whereas when asking my question, I had no idea about this restriction. – gregghz Dec 31 '12 at 19:45
  • There are a _lot_ of questions like yours on this site. Giving you a link explaining _why_ you can't do what you're doing seems more instructive than just telling you "move the templates to the headers". – Mat Dec 31 '12 at 19:48
  • no, that makes sense. And I don't mind if the question is closed. I just spent a lot of time googling those errors (especially the clang one, that may have been my mistake) and didn't come up with anything mentioning this particular restriction. I feel that perhaps the question would be helpful even if it has been covered before since it's not an "exact" duplicate. I don't know if that's enough to not close it though. – gregghz Dec 31 '12 at 19:51

2 Answers2

7

You have to implement your template functions in the .h file, not in the .cpp

Here's some further reading

Community
  • 1
  • 1
Foggzie
  • 9,691
  • 1
  • 31
  • 48
2

The compiler needs the definition in WaypointTree.cpp in order to generate the code for _waypoints->foreach([] (Waypoint *wp). So you must either include your cpp as well or define foreach in your header file.

Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198