[2018年5月29号]C++ primer 课后练习 第十六章 模版与泛型编程

16.9

函数模版就是一个公式,可用来生成针对特定类型的函数版本,模版定义以关键字template开始,后跟一个模版参数列表,这是一个逗号分割的一个或多个模版参数的列表

类模版是用来生成类的蓝图的,与函数模版的不同之处是,编译器不能为类模版推断模版参数类型,如我们已经多次看到的,为了使用类模版,我们必须在模版名后的尖扩号中提供额外信息

16.10

使用一个类模版时,我们必须提供额外信息,这些额外信息是显示模版实参列表,它们被绑定到模版参数.编译器使用这些模版实参来实例化出特定的类,当实例化一个类时,它会重写Blob模版,将模版参数T的每个实例替换为给定的模版实参,当类模版的静态成员被实例化后,每个实例都会有自己的static成员实例

16.11


修改后如下:

template <typename elemType> class ListItem;

template <typename elemType> class List { public: List<elemType>() = default; List<elemType>(const List<elemType>& ); List<elemType>& operator=(const List<elemType>&); ~List<elemType>() = default; void insert(ListItem<elemType>*ptr, elemType value); //listItem也是需要实例化才能使用的y private: ListItem<elemType> * front, * end; }; int main() { ::List<int> l; for (;;); return 0; }

16.12:

template <typename> class BlobPtr;
template <typename> class Blob;
template <typename T>
bool operator==(const Blob<T>&, const Blob<T>&);

template <typename T>
class Blob{
    friend class BlobPtr<T>;
    friend bool operator==(const Blob<T>&, const Blob<T>&);
public:
    typedef T value_type;
    typedef typename vector<T>::size_type size_type;
    Blob();
    Blob(initializer_list<T> il);
    size_type size() const {return data->size();}
    bool empty() const {return data->empty();}
    void push_back(const T& t){data->push_back(t);}
    void push_back(const T && t){data->push_back(std::move(t));}
    T& back();
    T& operator[](size_type t);
    void pop_back();
private:
    shared_ptr<vector<T>> data;
    void check(size_type i, const string & msg)const;
};

template <typename T>
void Blob<T>::check(size_type i, const string & msg) const{
    if(i >= data->size()){
        throw out_of_range(msg);
    }
}
template <typename T>
T& Blob<T>::back(){
    return data->back();
}
template <typename T>
Blob<T>::Blob():data(make_shared(vector<T>)){

}
template <typename T>
Blob<T>::Blob(initializer_list<T> il) : data(make_shared(vector<T>(il))) {

}

template <typename T>
T& Blob<T>::operator[](size_type t){
    check(t, "out of range");
    return ( *data)[t];
}

template <typename T>
void Blob<T>::pop_back() {
    data->pop_back();
}

template <typename T>
class BlobPtr {
public:
    BlobPtr():curr(0){}
    BlobPtr(Blob<T>&a, size_t sz = 0): wptr(a.data),curr(sz){}
    T& operator*()const{
        auto p = check(curr, "dereference past end");
        return (*p)[curr];
    }
    BlobPtr& operator++();
    BlobPtr& operator--();
private:
    shared_ptr<vector<T>> check(size_t, const string& )const;
    weak_ptr<vector<T>> wptr;
    size_t curr;

};
template <typename T>
BlobPtr& BlobPtr<T>::operator++(int){
    BlobPtr ret = *this;
    ++*this;
    return ret;
}

16.13

使用前置声明版本的==重载运算符

16.14

template <typename T>
class Screen {
    typedef T pos;
    friend istream& operator>>(istream& is, Screen<T> s);
    friend ostream& operator<<(ostream& is, Screen<T> s);
public:
    friend class Window_mgr;
    Screen() = default;
    Screen(pos wightVal, pos heightVal) :wight(wightVal), height(heightVal), contents(wightVal*heightVal, ' ') {
    }
    Screen(pos wightVal, pos heightVal, char contents) :wight(wightVal), height(heightVal), contents(wightVal*heightVal, contents) {
    }
    Screen& set(char);
    Screen& move(pos r, pos col);
    Screen& display(ostream& os);
    int getWight()const { return wight; }
    string& getContents() { return contents; }
    int getHeight()const { return height; }
    pos size()const;
private:
    pos cursor;
    pos wight, height;
    string contents;
    void do_displayer(ostream& os) {
        os << contents;
    }
};


template <typename T>
istream& operator>>(istream& is, Screen<T> s){
    T tmpH, tmpW;
    if(is>> tmpH >> tmpW){
        s = Sreen(tmpH, tmpW);
    }
    return is;
}
template <typename T>
ostream& operator<<(ostream& os, Screen<T> s){
    os << s.getWight() << " " << s.getHeight() << endl;
    return os;
}


template <typename T>
T Screen<T>::size()const {
    return height * wight;
}

class Window_mgr {
public:
    typedef  string::size_type ScreenIndex;
    void clear(ScreenIndex index);
private:
    vector<Screen<int>> screens{ Screen<int>(24, 80, ' ') };
};

void Window_mgr::clear(ScreenIndex index) {
    Screen<int> & s = screens[index];
    s.getContents() = string(s.getWight()*s.getHeight(), ' ');
}
template <typename T>
Screen<T>& Screen<T>::set(char c) {
    contents[cursor] = c;
    return *this;
}
template <typename T>
Screen<T>& Screen<T>::move(pos r, pos col) {
    cursor = wight * r + col;
    return *this;
}
template <typename T>
Screen<T>& Screen<T>::display(ostream& os) {
    do_displayer(os);
    return *this;
}

16.15

    friend istream& operator>>(istream& is, Screen<T> s);
    friend ostream& operator<<(ostream& is, Screen<T> s);
    template <typename T>
    istream& operator>>(istream& is, Screen<T> s) {
        T tmpH, tmpW;
        if (is >> tmpH >> tmpW) {
            s = Sreen(tmpH, tmpW);
        }
        return is;
    }
    template <typename T>
    ostream& operator<<(ostream& os, Screen<T> s) {
        os << s.getWight() << " " << s.getHeight() << endl;
        return os;
    }

16.16

template <typename T>
class Vec {
    friend bool operator==(const Vec& sv_0, const Vec& sv_1);
    friend bool operator!=(const Vec& sv_0, const Vec& sv_1);
    friend bool operator<(const Vec& sv_0, const Vec& sv_1);
public:
    Vec() :emlemnts(nullptr), first_free(nullptr), cap(nullptr) {}
    Vec(const Vec&);
    Vec(Vec&& s) :emlemnts(std::move(s.emlemnts)), first_free(std::move(s.first_free)), cap(std::move(s.cap)) {
        s.emlemnts = s.first_free = s.cap = nullptr;
    };
    Vec(initializer_list<T>);
    const T& operator[](size_t n)const {
        return emlemnts[n];
    };
    T& operator[](size_t n) {
        return emlemnts[n];
    };
    Vec& operator=(Vec&);
    Vec& operator=(initializer_list<T>);
    Vec& operator=(Vec&&s) {
        if (this != &s) {
            free();
            this->emlemnts = s.emlemnts;
            this->first_free = s.first_free;
            this->cap = s.cap;
            s.emlemnts = s.first_free = s.cap = nullptr;
        }
        return *this;
    };
    ~Vec();
    void push_back(const T&);
    T* begin()const { return emlemnts; }
    T* end()const { return first_free; }
    size_t size() { return first_free - emlemnts; };
    size_t capacity() { return cap - emlemnts; };
    void reserve(const size_t& n);
    void resize(const size_t& n);
private:
    T * emlemnts;
    T* first_free;
    T* cap;
    allocator<T> alloc;
    pair<T*, T* > alloc_n_copy(const T *, const T *);
    void chk_n_alloc() { if (size() == capacity()) { reallocate(); } }
    void reallocate();
    void free();

};

template <typename T>
bool operator==(const Vec<T>& sv_0, const Vec<T>& sv_1) {
    return (sv_0.emlemnts == sv_1.emlemnts) && (sv_0.first_free == sv_1.first_free) && (sv_0.cap == sv_1.cap);
}
template <typename T>
bool operator!=(const Vec<T>& sv_0, const Vec<T>& sv_1) {
    return !(sv_0 == sv_1);
}
template <typename T>
bool operator<(const Vec<T>& sv_0, const Vec<T>& sv_1) {
    size_t size_0 = sv_0.first_free - sv_0.emlemnts;
    size_t size_1 = sv_1.first_free - sv_1.emlemnts;
    if (size_0 != size_1) {
        return size_0 < size_1;
    }
    for (size_t i = 0; i < size_0; i++) {
        if ((*sv_0.emlemnts) != (*sv_1.emlemnts)) {
            return (*sv_0.emlemnts) < (*sv_1.emlemnts);
        }
    }
    return false;
}

template <typename T>
pair<T*, T* > Vec<T>::alloc_n_copy(const T * b, const T *e) {
    auto data = alloc.allocate(e - b);
    return { data, uninitialized_copy(b,e,data) };
}
template <typename T>
Vec<T>::~Vec() {
    free();
}
template <typename T>
void Vec<T>::push_back(const T& s) {
    chk_n_alloc();
    alloc.construct(first_free++, s);
}
template <typename T>
Vec<T>::Vec(const Vec<T>& s) {
    auto tmpAlloc = alloc_n_copy(s.begin(), s.end());
    emlemnts = tmpAlloc.first;
    emlemnts = tmpAlloc.second;
}

template <typename T>
Vec<T>::Vec(initializer_list<T> list) {
    for (initializer_list<T>::iterator it = list.begin(); it != list.end(); it++) {
        push_back(*it);
    }
}
template <typename T>
Vec<T>& Vec<T>::operator=(initializer_list<T> list) {
    for (initializer_list<T>::iterator it = list.begin(); it != list.end(); it++) {
        push_back(*it);
    }
    return *this;
}
template <typename T>
Vec<T>& Vec<T>::operator=(Vec& s) {
    auto tmpAlloc = alloc_n_copy(s.begin(), s.end());
    free();
    emlemnts = tmpAlloc.first;
    first_free = tmpAlloc.second;
    return *this;
}
template <typename T>
void Vec<T>::free() {
    //for (auto p = first_free; p != emlemnts;) {
    //    alloc.destroy(--p);
    //}
    for_each(emlemnts, first_free, [](T& a) {a.~T(); });
    alloc.deallocate(emlemnts, capacity());
}
template <typename T>
void Vec<T>::reallocate() {
    auto newcapacity = size() ? 2 * size() : 1;
    auto newdata = alloc.allocate(newcapacity);
    auto dest = newdata;
    auto elem = emlemnts;
    for (size_t i = 0; i != size(); i++)
        alloc.construct(dest++, move(*elem++));
    free();
    emlemnts = newdata;
    first_free = dest;
    cap = emlemnts + newcapacity;
}

template <typename T>
void Vec<T>::reserve(const size_t& n) {
    if (n < size()) {
        return;
    }
    auto newdata = alloc.allocate(n);
    auto dest = newdata;
    auto elem = emlemnts;
    for (size_t i = 0; i != size(); i++)
        alloc.construct(dest++, move(*elem++));
    free();
    emlemnts = newdata;
    first_free = dest;
    cap = emlemnts + n;
}
template <typename T>
void Vec<T>::resize(const size_t& n) {
    auto newdata = alloc.allocate(n);
    auto dest = newdata;
    auto elem = emlemnts;
    for (size_t i = 0; i != size() && i < n; i++)
        alloc.construct(dest++, move(*elem++));
    free();
    emlemnts = newdata;
    first_free = dest;
    cap = emlemnts + n;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值