16.1 Blob and BlobPtr class template

Blob.h

#pragma once
#include <vector>
#include <memory>
#include <stdexcept>
#include <string>

template <typename T> class BlobPtr;
template <typename T> 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==<T>(const Blob<T> &lhs, const Blob<T> &rhs);
public:
    Blob();
    Blob(std::initializer_list<T> il);
    template <typename T>
    template <typename Itr>
    Blob(Itr b, Itr e)
    	: data(std::shared_ptr<std::vector<T>>(b, e)) {}
    size_t size() const;
    bool empty() const;
    void push_back(const T&);
    void push_back(T &&);
    void pop_back();
    T &back() const;
    T &operator[](size_t index) const;

private:
    void check(size_t i, const std::string &msg) const;
    std::shared_ptr<std::vector<T>> data;
};

template <typename T>
Blob<T>::Blob() : data(new std::vector<T>) {}

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

template <typename T>
size_t Blob<T>::size() const {
    return data->size();
}

template <typename T>
bool Blob<T>::empty() const {
    return data->empty();
}

template <typename T>
void Blob<T>::push_back(const T &t) {
    data->push_back(t);
}

template <typename T>
void Blob<T>::push_back(T &&t) {
    data->push_back(std::move(t));
}

template <typename T>
void Blob<T>::pop_back() {
    check(0, "pop back on empty Blob");
    data->pop_back();
}

template <typename T>
T &Blob<T>::back() const {
    check(0, "get back on empty Blob");
    return data->back();
}

template <typename T>
T &Blob<T>::operator[](size_t index) const {
    check(index, "get element pass the boundary");
    return (*data)[index];
}

template <typename T>
void Blob<T>::check(size_t index, const std::string &msg) const {
    if (index >= data->size()) {
        throw std::out_of_range(msg);
    }
}

BlobPtr.h

#pragma once
#include "Blob.h"

template <typename T>
class BlobPtr{
public:
    BlobPtr() = default;
    BlobPtr(Blob<T> &b, size_t sz);
    T& operator*() const;
    BlobPtr& operator++();
    BlobPtr& operator--();
private:
    std::shared_ptr<std::vector<T>>
        check(size_t, const std::string &) const;
    std::weak_ptr<std::vector<T>> wptr;
    size_t curr = 0;
};

template <typename T>
BlobPtr<T>::BlobPtr(Blob<T> &b, size_t sz)
    : wptr(b.data), curr(sz) {}

template <typename T>
T& BlobPtr<T>::operator*() const {
    auto ptr = check(curr, "dereference pass the end");
    return (*ptr)[curr];
}

template <typename T>
BlobPtr<T> &BlobPtr<T>::operator++() {
    check(curr + 1, "increase index pass the end");
    ++curr;
    return *this;
}

template <typename T>
BlobPtr<T> &BlobPtr<T>::operator--() {
    check(curr - 1, "decrease index pass the beg");
    --curr;
    return *this;
}

template <typename T>
std::shared_ptr<std::vector<T>>
    BlobPtr<T>::check(size_t index, const std::string &msg) const {
        auto p = wptr.lock();
        if (p) {
            if (p->size() > index) {
                return p;
            } else {
                throw std::out_of_range(msg);
            }
        } else {
            throw "unbind BlobPtr";
        }
}

main.cpp

#include <iostream>
#include "Blob.h"
#include "BlobPtr.h"

using namespace std;

int main() {
    std::initializer_list<int> il{1,2,3,4,5};
    Blob<int> b(il);
    cout << b.empty() << endl;
    cout << b.size() << endl;
    cout << b.back() << endl;
    b.push_back(6);
    cout << b.back() << endl;
    b.pop_back();
    cout << b.back() << endl;
    cout << b.size() << endl;

	cout << "=========================================" << endl;
	std::initializer_list<int> il{1,2,3,4,5};
    Blob<int> b(il);
    BlobPtr<int> ptr(b, 0);
    cout << *ptr << endl;
    cout << *++ptr << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值