自定义矢量类模板失败的初始值设定项

时间:2015-12-03 14:49:58

标签: c++ class templates vector

我正在为课堂做一个项目,我想我在这本书之后让自己感到困惑。

我们正在构建一个带有模板的自定义矢量类,它将经过一系列测试。

使用我当前的代码,在初始化以下语句时失败。

Vector<int> v {1,2,3};

这是我的档案。

vector.hpp

#ifndef VECTOR_HPP
#define VECTOR_HPP

#include <memory>

template<typename T, typename A = std::allocator<T> >
struct Vector_base {
    A alloc;
    T* elem;
    T* space;
    T* last;

    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); }
    Vector_base(const Vector_base&) = delete;

    Vector_base& operator=(const Vector_base&) = delete;
    Vector_base(Vector_base&&);
    Vector_base& operator=(Vector_base&&);
};

template<typename T, typename A = std::allocator<T> >
class Vector {
    Vector_base<T,A> vb;
    void destroy_elements();
public:
    using size_type = typename A::size_type;

    bool is_empty() const
    {
        return this->empty();
    }

    explicit Vector(size_type n, const T& val = T(), const A& = A());

    Vector() {}

    Vector(const Vector& a);
    Vector& operator=(const Vector& a);

    Vector(Vector&& a);
    Vector& operator=(Vector&& a);

    ~Vector() { destroy_elements(); }

    size_type size() const { return vb.space-vb.elem; }
    size_type capacity() const { return vb.last-vb.elem; }

    void reserve(size_type);

    void resize(size_type, const T& = {});
    void clear() { resize(0); }
    void push_back(const T&); 
};

#endif

vector.cpp

#include "vector.hpp"
#include <memory>

//template<typename T, typename A>
Vector_base<T,A>::Vector_base(Vector_base&& a) : alloc{a.alloc}, elem{a.elem}, space{a.space}, last{a.space}
{
    a.elem = a.space = a.last = nullptr;
}

//template<typename T, typename A>
Vector_base<T,A>& Vector_base<T,A>::operator=(Vector_base&& a)
{
    swap(*this,a);
    return *this;
}

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

    vb.space=vb.elem;
}

//template<typename For, typename T>
void uninitialized_fill(For beg, For end, const T& x)
{
    For p;
    try {
        for (p=beg; p!=end; ++p)
            ::new(static_cast<void*>(&*p)) T(x);
    }
    catch (...) {
        for (For q = beg; q!=p; ++q)
            (&*q)-> ~T();
        throw;
    }
}

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


//template<typename T, typename A>
Vector<T,A>::Vector(const Vector<T,A>& a) : vb{a.alloc,a.size()}
{
    std::uninitialized_copy(a.begin(),a.end(),vb.elem);
}

//template<typename T, typename A>
Vector<T,A>::Vector(Vector<T,A>&& a) : vb{move(a.vb)} { }

/*template<typename T, typename A>
Vector<T,A>::Vector(const Vector& a)
{

}*/

//template<typename T, typename A>
Vector<T,A>& Vector<T,A>::operator=(Vector<T,A>&& a)
{
    clear();
    swap(vb,a.vb);
    return *this;
}

//template<typename T, typename A>
Vector<T,A>& Vector<T,A>::operator=(const Vector& a)
{
    if(capacity() < a.size())
    {
        Vector temp {a};
        swap(*this,temp);
        return *this;
    }

    if (this == &a) { return *this; }

    size_type sz = size();
    size_type asz = a.size();
    vb.alloc = a.vb.alloc;
    if (asz<=sz) 
    {
        copy(a.begin(),a.begin()+sz,vb.elem);
        for(T* p = vb.elem+asz; p!=vb.space; ++p)
            p-> ~T();
    }
    else
    {
        copy(a.begin(),a.begin()+sz,vb.elem);
        uninitialized_copy(a.begin()+sz,a.end(),vb.space);
    }
    vb.space = vb.elem+asz;
    return *this;
}

//template<typename T, typename A>
void safe_assign(Vector<T,A>& a, Vector<T,A> b)
{
    swap(a,b);
}

//template<typename T, typename A>
void Vector<T,A>::reserve(size_type newalloc)
{
    if (newalloc<=capacity()) return;
    Vector_base<T,A> b {vb.alloc,newalloc-size()};
    uninitialized_move(vb.elem,vb.elem+size(),b.elem);
    swap(vb,b);
}

//template<typename In, typename Out>
Out uninitialized_move(In b, In e, Out oo)
{
    using T = typename std::iterator_traits<Out>::value_type;
    for (; b!=e; ++b,++oo) {
        new(static_cast<void*>(&*oo)) T{move(*b)};
        b-> ~T();
    }
    return oo;
}

//template<typename T, typename A>
void Vector<T,A>::resize(size_type newsize, const T& val)
{
    reserve(newsize);
    if (size()<newsize)
        uninitialized_fill(vb.elem+size(),vb.elem+newsize,val);
    else
        destroy(vb.elem+newsize,vb.elem+size());
    vb.space = vb.elem+newsize;
}

//template<typename In>
void destroy(In b, In e)
{
    using T = typename std::iterator_traits<In>::value_type;
    for (; b!=e; ++b)
        b-> ~T();
}

//template<typename T, typename A>
void Vector<T,A>::push_back(const T& val)
{
    if (capacity()==size())
        reserve(size()?2*size():8);
    vb.alloc.construct(&vb.elem[size()],val);
    ++vb.space;
}

我在这里缺少什么?

1 个答案:

答案 0 :(得分:0)

据我所知,所有模板代码都必须在头文件中,因为实际的实现是由编译器完成的。初始化失败的原因是编译器无法找到函数的定义。

将所有代码移至vector.hpp

编辑:此外,您还需要一个以initializer_list为参数的构造函数。