2

I have a problem with compiling and linking the main.cxx and Vec.cxx files, which are shown below.

To compile, I am using g++ with the following command:g++ -std=c++11 -c main.cxx Vec.cxx. To link, simply g++ main.o Vec.o. But doing this I get undefined reference errors to the create and uncreate functions, which are used by the constructors and the destructor.

Vec.cxx:

// Vec.cxx
// Source file for Vec template class header.

#include "Vec.h"

#include <memory>

template <class T> Vec<T>& Vec<T>::operator=(const Vec& rhs){

  if(&rhs != this){

    // free array in the left hand side
    uncreate();

    create(rhs.begin(),rhs.end());

  }

  return *this;
}

template <class T> void Vec<T>::create(){
  data = avail = limit = 0;

  return;
}


template <class T> void Vec<T>::create(size_type n, const T& val){
  data = alloc.allocate(n);
  limit = avail = data + n;
  std::uninitialized_fill(data,limit,val);

  return;
}


template <class T> void Vec<T>::create(const_iterator b,const_iterator e){
  data = alloc.allocate(e-b);
  limit = avail = std::uninitialized_copy(b,e,data);

  return;
}


template <class T> void Vec<T>::uncreate(){
  if (data) {
    // Destroy (in reverse order) the constructed elements;
    iterator it = avail;
    while(it != data){
      alloc.destroy(--it);
    }

    // Return all the space that was allocated
    alloc.deallocate(data, limit-data);
  }

  data = limit = avail = 0;

  return;
}


template <class T> void Vec<T>::grow(){
  size_type new_size = std::max(2* (limit-data), std::ptrdiff_t(1));

  iterator new_data = alloc.allocate(new_size);
  iterator new_avail = uninitialized_copy(data,avail,new_data);

  uncreate();

  data = new_data;
  avail = new_avail;
  limit = data + new_size;

  return;
}


template <class T> void Vec<T>::unchecked_append(const T& val){
  alloc.construct(avail++,val);

  return;
}

Vec.h:

#ifndef VEC_H
#define VEC_H

#include <memory>

template<class T> class Vec{

 public:
  // define names 
  using iterator = T*;
  using const_iterator = const T*;
  using size_type = size_t;
  using value_type = T;

  // Size and index operators
  size_type size() const { return avail - data; }
  T& operator[] (size_type i) { return data[i]; }
  const T& operator[] (size_type i) const { return data[i]; }


  // Constructors
  Vec() { create(); }
  explicit Vec(size_type n, const T& val = T()) { create(n, val); }
  Vec(const Vec& v) { create(v.begin(),v.end()); }

  // Destructor
  ~Vec() { uncreate(); }

  // Assignment operator
  Vec& operator=(const Vec&);

  // push_back function
  void push_back(const T& val){
    if(avail == limit){
      grow();
    }

    unchecked_append(val);
    return;
  }

  // Iterators
  iterator begin() { return data; }
  const_iterator cbegin() const { return data; }
  const_iterator begin() const { return data; }

  iterator end() { return limit; }
  const_iterator end() const { return limit; }
  const_iterator cend() const { return limit; }

 private:
  iterator data;    // First element in Vec
  iterator avail;   // One past the last allocated memory element
  iterator limit;   // One past the last element in Vec

  std::allocator<T> alloc;

  void create();
  void create(size_type, const T&);
  void create(const_iterator,const_iterator);

  void uncreate();

  void grow();
  void unchecked_append(const T&);
};


#endif

main.cxx:

#include "Vec.h"

int main(int argc, char **argv){

  Vec<int> v(10,2);


  return 0;
}

Edit: Thankyou for marking as duplicate, the link resolved my question. I moved the functions into the header file and everything works now.

H Huwitz
  • 21
  • 2

0 Answers0