undefiened reference [дубликат]

250
02 ноября 2017, 07:30

На данный вопрос уже ответили:

  • Ссылка на неразрешенный внешний символ (возможные причины) 1 ответ

Выдает вот такую ошибку. Объявления вроде есть, а в коде их не видит. makefile и код в спойлерах ниже

main.o: In function `main':
main.cpp:(.text+0x2b): undefined reference to 
`containers::vector<int>::push_back(int&&)'
main.cpp:(.text+0x45): undefined reference to 
`containers::vector<int>::push_back(int&&)'
main.o: In function `void outarr<int>(containers::vector<int>&)':     
main.cpp   (.text._Z6outarrIiEvRN10containers6vectorIT_EE
[_Z6outarrIiEvRN10containers6vectorIT_EE]+0x22): 
undefined reference to `containers::vector<int>::size()'
main.cpp:
(.text._Z6outarrIiEvRN10containers6vectorIT_EE
[_Z6outarrIiEvRN10containers6vectorIT_EE]+0x3d):  
undefined reference to `containers::vector<int>::operator[](int)'

makefile:

all: vector
vector: main.o vector.o
    g++ main.o vector.o -o vector
main.o: main.cpp
    g++ -c main.cpp
vector.o: vector.cpp
    g++ -c vector.cpp
clear:
    rm -rf *.o 

main.cpp

#include "vector.h"
#include <iostream>
using namespace containers;
template<class T>
void outarr(vector<T>& v) {
    for(int i = 0; i < v.size(); ++i)
         std::cout << v[i] << "\t";
} 
int main() {
    vector<int> test;
    test.push_back(0);
    test.push_back(3);
    outarr<int>(test);
    return 0;
}

vector.h

#ifndef CONTAINER_VECTOR
#define CONTAINER_VECTOR
#include <cstddef>
#include <initializer_list>
namespace containers {
template<class T>
class vector {
private:
    T* array;
    std::size_t vector_size = 0;
    std::size_t vector_capacity;
public:
    vector() {}
    vector(std::initializer_list<T> init);
    vector(std::size_t size);
    vector(vector& other);
    ~vector() { delete[] array; }
    std::size_t size();
    std::size_t capacity();
    void reserve(std::size_t size);
    void push_back(const T& value);
    void push_back(T&& value);
    void insert(std::size_t pos, const T& value);
    void insert(std::size_t pos, T&& value);
    T&   pop_back();
    void clear();
    void erease(std::size_t pos);
    void erease(std::size_t from, std::size_t to);
    T& operator[](int index);
    //T& operator=(T& other);
};
}

#endif

vector.cpp

#include "vector.h"
#define tplate template<class T>
namespace containers {
tplate
vector<T>::vector(std::initializer_list<T> init) {
    vector_size = init.size();
    array = new T[vector_size];
    for(int i = 0; i < vector_size; ++i)
        array[i] = init[i];
}
tplate
vector<T>::vector(std::size_t size) {
    vector_size = size;
    array = new T[vector_size];
}
tplate
vector<T>::vector(vector& other) {
    vector_size = other.vector_size;
    array = new T[vector_size];
    for(int i = 0; i < vector_size; ++i)
        array[i] = other[i];
}
tplate
std::size_t vector<T>::size() { return vector_size; }
tplate
std::size_t vector<T>::capacity() { return vector_capacity; }
tplate
void vector<T>::reserve(std::size_t size) {
    T* newarr = new T[size];
    for(int i = 0; i < vector_size; ++i)
        newarr[i] = array[i];
    vector_size = size;
    delete[] array;
    array = newarr;
}
tplate
void vector<T>::push_back(const T& value) {
    if(vector_size <= vector_capacity) 
        reserve(++vector_size);
    array[vector_capacity] = value;
    ++vector_capacity;
}
tplate
void vector<T>::push_back(T&& value) {
    if(vector_size <= vector_capacity) 
        reserve(++vector_size);
    T* newel = value;
    array[vector_capacity] = *newel;
    ++vector_capacity;
}
tplate
void vector<T>::insert(std::size_t pos, const T& value) {
    if(pos > vector_capacity) {
        vector_size = pos;
        vector_capacity = pos;
        reserve(vector_size);
    }
    for(int i = vector_size; i > pos+1; --i)
        array[i] = array[i-1];
    array[pos] = value;
} 
tplate
T& vector<T>::operator[](int index) {
    return array[index];
}
} // namespace containers
#undef tplate
Answer 1

Для начала избавтись от

#define tplate template<class T>

А так, тело шаблонных функций/классов должно быть в .h файле, дя красоты его можно вынести в отдельный .inl файл и подключить снизу в .h файле.

Либо, сделать явную инстанциацию шаблоного класса для определенного типа в .cpp файле, в том файле где "видно" тела шаблонных методов

template class vector<int>;
Answer 2

Стандартная ошибка. Реализация шаблона должна быть доступна, без этого не происходит его инстанцирование. Так что переместите код из vector.cpp в vector.h - иначе происходит следующее: при компиляции main.cpp инстанцирования нет (как инстанцировать то, чего незнаешь?), а в vector.cpp опять же инстанцирования нет - потому что раз класс не используется - зачем его инстанцировать?

Можно, конечно, явно указать в vector.cpp на необходимость инстанцирования для того или иного типа, но это способ не лучший - вдруг понадобится вектор еще какого-то типа?

И еще, на всякий случай - надеюсь, вы знаете, что в

void push_back(T&& value);

value - универсальная ссылка, а не r-ссылка?

Судя по

T* newel = value;
array[vector_capacity] = *newel;

я вообще не пойму, чем вы ее считаете... Указателем на T?

И последнее - вот такие вещи

#define tplate template<class T>

отнюдь не способствуют пониманию кода, особенно если их становится много. Экономия, не стоящая того. Да и тогда уж хотя бы назовите TPLATE - чтоб хотя бы сразу видеть, что это макрос.

READ ALSO
Почему не работает программа?

Почему не работает программа?

Почему не работает программа? после выполнения операции "do

204
typedef и пользовательский тип [дубликат]

typedef и пользовательский тип [дубликат]

На данный вопрос уже ответили:

261
Количество компонент связности

Количество компонент связности

Данный код считает максимальную компоненту связностиКак найти их количество? Например,

311