Search code examples
c++templatespointersgeneric-programming

C++ Losing Template Data


I don't consider myself all that knowledgeable in C++ but I'm having a hard time with this concept. So I have a class the holds some template datatype and a double. I want the m_data variable to be generic, but right now I'm only testing with an unsigned int. When I call the function SetData() with say a pointer to an unsigned int I lose the info the pointer is pointing to. This happens when I go out of scope, so I felt I need to do a deep copy of it...

I tried many different constructors and assignment operators but I still lose the info... I feel I'm missing something obvious about templates here.If anyone could point me in the right direction as to why the data is being lost I would be very grateful.

Small bit of code:

template<typename T>
class PointNode {

 public:

  PointNode(double p){ m_point = p;}
  ~PointNode();

 void SetData(T  * data);
 T * GetData() const;

  private:

   double m_point;
   T *m_data;

 };

template<typename T>
void PointNode::SetData(T * data)
{
  m_data = data;
}

template<typename T>
T * PointNode::GetData()
{
  return m_Data;
}

OK some more info. This class is being stored in a map that is a member of another class. Heres a bit of it.

 template<typename T>
class AuMathPointTreeT
{

  public:

  //Member Variables 

  double m_dTolerance;  

  unsigned int m_cPoint;         


  map<VectorKey, PointNode<T> > m_tree; /*map posing as a tree */

  typename map<VectorKey, PointNode<T> >::iterator iter;   /* iterator  */
  pair< typename map<VectorKey, PointNode<T> >::iterator, bool > return_val;

  /* Tree methods */

  //constructor
  AuMathPointTreeT(double tol);

 ...
};

In another program I'm using this class, creating node and setting the template data like so

if (node = pnttree.AddPoint(point) )
{
    unsigned int * data = new unsigned int();
    *data = pntCount;
    node->SetData(data);
    ++pntCount;
}

UPDATE: Ok discovered the culprit of what's wrong, and would like suggestions on how to approach it. When I insert a node into the map class a few functions are called in the process and im losing the original pointer to the newly allocated node class object. Here is what I'm doing.

template<typename T>
PointNode<T> * AuMathPointTreeT<T>::
AddPoint(double point)
{
  PointNode<T> * prNode = MakeNode(point);

  m_cPoint++;

  return prNode;
} 

template<typename T>
PointNode<T> *  AuMathPointTreeT<T>::
MakeNode(double point)
{
  PointNode<T> * prNode = new PointNode<T>;

    //set the contents for the node just performs a few calcs on the values

  prNode->SetNode(point, m_dTolerance);


  //Create the key class using the 
  VectorKey key(point, m_dTolerance);

  //Store the key,node as a pair for easy access 
  return_val = m_tree.insert( pair<VectorKey, PointNode<T> >(key, *prNode) );
  if (return_val.second == false)
    prNode = NULL;

  unsigned int * test = new unsigned int;
  *test = 55;
  prNode->SetData(test);  //if call this here its no longer the right pointer 

  return prNode;
}

So after looking at this... I really still want to return a pointer and use it. But maybe the iterator being held by return_val? Im open on suggestions for all aspects too.. Sorry this question has been a mess :\


Solution

  • I don't think this has anything to do with the use of templates. Once a local variable goes out of scope, its location on the stack could be over-written by other data.

    If you expect the template class instance to out-live the local variable whose address is passed to SetData, you should consider allocating the data on the heap not the stack. Either way, I'd suggest replacing the raw m_data pointer with an appropriate smart pointer. For example, the use of shared_ptr<> in the template class and its client code should reduce the amount of data copying while at the same time ensuring the data remains valid regardless of whether or not the original data variable is in scope.