【发布时间】:2015-12-03 14:49:57
【问题描述】:
我正在为班级做一个项目,我想我在读完这本书后让自己陷入了困惑。
我们正在构建一个带有模板的自定义矢量类,它将通过一系列测试。
使用我当前的代码,初始化以下语句时失败。
Vector<int> v {1,2,3};
这是我的文件。
矢量.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
矢量.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;
}
我在这里错过了什么?
【问题讨论】:
-
你需要一个构造函数来获取
std::initializer_list。另见stackoverflow.com/q/495021/1782465 -
@Clix 为什么你注释掉了
template行?你期待{1,2,3}调用Vector(size_type n, const T& val, const A&)过载吗? -
@LogicStuff 我忘了我还有他们的评论。另一个板上的某个人建议在除头文件之外的任何内容中都不允许使用模板。
-
是的,没错。但解决方案是将整个定义(带有
template前缀)移动到头文件中。没有其他办法。 -
我确实最终移动了它们。我仍然收到与以前相同的错误。我相信问题出在 Angew 的建议上。不过,我不太确定如何实现它。
标签: c++ class templates vector