我正在为课堂做一个项目,我想我在这本书之后让自己感到困惑。
我们正在构建一个带有模板的自定义矢量类,它将经过一系列测试。
使用我当前的代码,在初始化以下语句时失败。
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;
}
我在这里缺少什么?
答案 0 :(得分:0)
据我所知,所有模板代码都必须在头文件中,因为实际的实现是由编译器完成的。初始化失败的原因是编译器无法找到函数的定义。
将所有代码移至vector.hpp
。
编辑:此外,您还需要一个以initializer_list
为参数的构造函数。