Реализация упрощенного векторного класса C ++ - не компилируется - PullRequest
1 голос
/ 16 декабря 2011

Глава 11 Accelerated C ++ описывает реализацию шаблонных классов, используя в качестве примера упрощенную версию векторного класса STL.Упражнение 11-6 требует, чтобы мы добавили методы .erase() и .clear() в класс, поэтому сначала я скопировал окончательный код прямо из книги и попытался скомпилировать, но это не удалось.Затем я переместил все определения функций в файл .h (при необходимости удалив Vec<T>:: и т. Д.) И скомпилировал только мой main.cpp, который сработал.

Вот весь мой код:

main.cpp

#include <iostream>
#include "Vec.h"

using std::cout;
using std::endl;

int main()
{
    Vec<int> v;
    for (int i = 1; i < 10; ++i)
        v.push_back(i);

    for(Vec<int>::const_iterator iter = v.begin();
        iter != v.end(); ++iter)
        cout << *iter << endl;

    return 0;
}

Vec.h

#ifndef GUARD_Vec_h
#define GUARD_Vec_h

#include <cstddef>
#include <memory>

template <class T> class Vec {
public:
    // member variables
    typedef T* iterator;
    typedef const T* const_iterator;
    typedef std::size_t size_type;
    typedef T value_type;
    typedef T& reference;
    typedef const T& const_reference;

    // constructors + destructors
    Vec() { create(); }
    explicit Vec(size_type n, const T& t = T()) { create(n, t); }
    Vec(const Vec& v) { create(v.begin(), v.end()); }
    ~Vec() { uncreate(); }

    // methods
    T& operator[](size_type i) { return data[i]; }
    const T& operator[](size_type i) const { return data[i]; }

    void push_back(const T& t) {
        if (avail == limit)
            grow();
        unchecked_append(t);
    }

    size_type size() const { return avail - data; }

    iterator begin() { return data; }
    const_iterator begin() const { return data; }

    iterator end() { return avail; }
    const_iterator end() const { return avail; }

private:
    iterator data;
    iterator avail;
    iterator limit;

    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 GUARD_Vec_h

Vec.cpp

#include <algorithm>
#include <cstddef>
#include <memory>
#include "Vec.h"

using std::allocator;
using std::max;
using std::uninitialized_copy;
using std::uninitialized_fill;
using std::ptrdiff_t;

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

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

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

template <class T> void Vec<T>::uncreate()
{
    if (data) {
        iterator it = avail;
        while (it != data)
            alloc.destroy(--it);

        alloc.deallocate(data, limit - data);
    }

    data = limit = avail = 0;
}

template <class T> void Vec<T>::grow()
{
    size_type new_size = max(2 * (limit - data), 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;
}

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

Почему не компилируется?

1 Ответ

0 голосов
/ 05 ноября 2012

Проблема со всеми функциями шаблона. Когда вы пишете функцию Template, компилятор создает шаблон - то есть создает конкретную версию функции с типами, необходимыми для запуска кода. Поэтому, когда вы звоните

Vec<int> v;

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

...