0

I have the following templated classes,

template <typename Real>
class Marker {

 typedef Wm5::Vector3<Real> Position ;
 typedef Wm5::Vector3<Real> Normal ;
 typedef Wm5::Vector3<Real> Color ;

 public:

  Marker(int id = -1, Position position = Wm5::Vector3<Real>::ZERO, Normal normal = Wm5::Vector3<Real>::ZERO, Color color = Wm5::Vector3<Real>::ZERO)
: id_(id), position_(position), normal_(normal), color_(color), cluster_(-1) {}

  ~Marker() {}

 private:

  int id_ ;
  Position position_ ;
  Normal normal_ ; 
  Color color_ ;
  int cluster_ ;

};


template <typename T> 
class MarkerSet {

    typedef Marker<T> MarkerT ;      
    typedef std::vector<MarkerT> MarkerVector ;

public:

    MarkerSet::MarkerSet(int id = -1, MarkerVector markers = MarkerVector()) 
   {id_ = id; markers_ = markers;}      

   MarkerSet::~MarkerSet() {}

private:

    int id_ ;   
    MarkerVector markers_ ;

} ;

When I try to create a MarkerSet object by

MarkerSet<double> markerSet ; 

Getting this linker error,

error LNK2001: unresolved external symbol "public: __thiscall     MarkerSet<double>::MarkerSet<double>(int,class std::vector<class Marker<double>,class std::allocator<class Marker<double> > >)" (??0?$MarkerSet@N@@QAE@HV?$vector@V?$Marker@N@@V?$allocator@V?$Marker@N@@@std@@@std@@@Z)

I would be extremely grateful if somebody could give me a pointer in the right direction with regards to what I have done wrong.

Edit:

Ok I have narrowed it down to something rather odd.

in .h

  MarkerSet(int id = -1, MarkerVector markers = MarkerVector()) 
{id_ = id; markers_ = markers;}    

builds fine

Rather than in .h

 MarkerSet(int id = -1, MarkerVector markers = MarkerVector()) ;

in .cpp

 template <typename T>
 MarkerSet<T>::MarkerSet(int id, MarkerVector markers) {

  id_ = id ;
  markers_ = markers ;

}

Errors out in the way described above.

Any thoughts?

oracle3001
  • 1,090
  • 19
  • 31

2 Answers2

1

Can you try using a different compiler? I tried playing with it and the following works fine for me with gcc. I eliminated the Wm5 members as I don't have those. Pasting the header and cpp:

test.h

#include <vector>

template <typename Real>
class Marker {

 public:

  Marker(int id = -1,int _position=1)
    : id_(id), position(_position){}

  ~Marker() {}

 private:

  int id_ ;
  int position ;
  Real r;

};


template <typename T> 
class MarkerSet {

    typedef Marker<T> MarkerT ;      
    typedef std::vector<MarkerT> MarkerVector ;

public:

    MarkerSet(int id = -1, MarkerVector markers = MarkerVector()) 
      {id_ = id; markers_ = markers;std::cout<<"Called"<<std::endl;}      

   ~MarkerSet() {}

private:

    int id_ ;   
    MarkerVector markers_ ;

} ;

test.cpp

#include <iostream>
#include <vector>
#include "test.h"

using namespace std;


int main(int argc, const char **argv) {
  cout<<"Hello"<<endl;
  MarkerSet<double> ms;
  return -1;

}

cmd:

bash$ ./test
Hello
Called
bash$ 

Template class definition need to be in the header:

Why do C++ template definitions need to be in the header?

Community
  • 1
  • 1
Sid
  • 7,511
  • 2
  • 28
  • 41
  • Ok I have got it to build now on my VS2010 machine....I have no idea what is different between this MarkerSet(int id = -1, MarkerVector markers = MarkerVector()) {id_ = id; markers_ = markers;std::cout<<"Called"< MarkerSet::MarkerSet(int id, MarkerVector markers) {id_ = id ; markers_ = markers ;} in the .cpp files – oracle3001 Mar 13 '12 at 20:24
  • I am not including MarkerSet:: before the function names. As definition is inside of the class you don't need to qualify by class name. gcc actually complained about it. Also all definitions are in the header as these are template classes. – Sid Mar 13 '12 at 20:27
  • I understand. See edit above as clearer explanation of problem still having. – oracle3001 Mar 13 '12 at 20:32
  • You cannot put template class definitions in .cpp files. You need to put them in the headers for them to be available at compile time. This must be your issue. Here, read this: http://stackoverflow.com/questions/5180357/why-do-c-template-definitions-need-to-be-in-the-header – Sid Mar 13 '12 at 20:48
  • Done...Still getting the hang of this stack overflow thing :-) – oracle3001 Mar 13 '12 at 21:06
0

May it be so that you do not #include actual contructor body so that the linker does not generate required code for MarkerSet<double>::MarkerSet<double>(int,class std::vector<class Marker<double>,class std::allocator<class Marker<double> > >)"?

gluk47
  • 1,812
  • 20
  • 31
  • Just tried changing the extra-qualified possibility and still getting the same error. Using VS2010 as compiler. – oracle3001 Mar 13 '12 at 18:00
  • I am not sure quite what you mean by "do not #include actual constructor body". – oracle3001 Mar 13 '12 at 18:16
  • SOrry, I meant exactly what Sid suggested, either moving constructor body to the header, or #include cpp-file with the body, not only include header with prototype. My bad, I should have clarified it. – gluk47 Mar 14 '12 at 21:20