16.1 Blob and BlobPtr class template

mac2024-12-17  14

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; }
最新回复(0)