0

Some "undefined reference error" questions are already posted on StackOverflow but I couldn't find solution to my problem.

My project contains 5 files: 5.cpp vector_base.h vector_base.cpp vector.h vector.cpp

I compile it with:

g++ -std=c++11 vector_base.cpp vector.cpp 5.cpp -o 5

And get the following error:

/tmp/ccO8NeGJ.o: In function `main':
5.cpp:(.text.startup+0x21): undefined reference to `Vector<int, std::allocator<int> >::Vector(unsigned int, int const&, std::allocator<int> const&)'
5.cpp:(.text.startup+0x2b): undefined reference to `Vector<int, std::allocator<int> >::destroy_elements()'
collect2: error: ld returned 1 exit status

well, code looks fine for me. Where did I mess up?

The code is as follows:

5.cpp

#include "vector.h"

int main() {
    Vector<int> a{10, 0};
}

vector.h

#ifndef VECTOR_H
#define VECTOR_H

#include "vector_base.h"

template<class T, class A = std::allocator<T>>
class Vector {
private:
    vector_base<T,A> vb;
    void destroy_elements();

public:
    using size_type = unsigned int;

    explicit Vector(size_type n, const T& val = T(), const A& a = A());
    ~Vector() { destroy_elements(); }
};

#endif //VECTOR_H

vector.cpp

#include "vector.h"

#include <algorithm>
#include <memory>

template<class T, class A>
Vector<T,A>::Vector(size_type n, const T& val, const A& a)
    :vb{a, n}
{
    std::uninitialized_fill(vb.elem, vb.elem + n, val);
}

template<class T, class A>
void Vector<T,A>::destroy_elements()
{
    for(T* p = vb.elem; p!=vb.space; ++p){
        p->~T();
    }
    vb.space=vb.elem;
}

vector_base.h

#ifndef VECTOR_BASE_H
#define VECTOR_BASE_H

#include <memory>

template<class T, class A = std::allocator<T>>
struct vector_base {

    T* elem;
    T* space;
    T* last;
    A alloc;

    using size_type = unsigned int;

    vector_base(const A& a, typename A::size_type n)
        :alloc{a}, elem{alloc.allocate(n)}, space{elem+n}, last{elem+n} {}

    ~vector_base() { alloc.deallocate(elem, last-elem); }
};
#endif //VECTOR_BASE_H

vector_base.cpp

#include "vector_base.h"
#include <algorithm>

template<class T, class A>
vector_base<T,A>::vector_base(const vector_base&& a)
    :alloc{a.alloc}, elem{a.elem}, space{a.space}, last{a.last}
{
    a.elem = a.space = a.last = nullptr;
}

template<class T, class A>
vector_base<T,A>& vector_base<T,A>::operator=(const vector_base&& a)
{
    swap(*this, a);
    return *this;
}

I tried compile every cpp file separately and then link all but it didn't work also.

  • 2
    Related ? http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – Fantastic Mr Fox Sep 23 '15 at 20:50
  • 1
    _@tomtom_ It's not linking order in this particular case, but otherwise it matters, yes. – πάντα ῥεῖ Sep 23 '15 at 20:52
  • Solution: At the end of each *.h file I included related *.cpp file. And then in compilation I omitted vector.cpp and vector_base.cpp files: g++ 5.cpp -o 5 –  Sep 23 '15 at 21:11
  • @tomtom Refer to the duplicate marked answers. These actually solve your problem. Including `.cpp` files from template headers confuse your build system. Choose a different source file extension for these. – πάντα ῥεῖ Sep 23 '15 at 21:13

0 Answers0