diff --git a/ch16/README.md b/ch16/README.md index 649d894a..b11055d4 100644 --- a/ch16/README.md +++ b/ch16/README.md @@ -243,11 +243,17 @@ Solution from [How is a template instantiated? - Stack Overflow](https://stackov > Revise your `Blob` class to use your version of `shared_ptr` rather than the library version. +[Blob with SharedPtr](ex16_29_blob.h) | [test](ex16_29_blob_test.cpp) + ## Exercise 16.30 Rerun some of your programs to verify your `shared_ptr` and revised `Blob` classes. (Note: Implementing the `weak_ptr` type is beyond the scope of this Primer, so you will not be able to use the `BlobPtr` class with your revised `Blob`.) +check [Exercise 16.28](#exercise-1628) + ## Exercise 16.31 ->Explain how the compiler might inline the call to the deleter if we used `DebugDelete` with `unique_ptr`. \ No newline at end of file +>Explain how the compiler might inline the call to the deleter if we used `DebugDelete` with `unique_ptr`. + +The compiler will set the default deleter type as `DebugDelete`, which will be executed is known at compile time. \ No newline at end of file diff --git a/ch16/ex16.29/Blob.h b/ch16/ex16.29/Blob.h deleted file mode 100644 index 867a16d3..00000000 --- a/ch16/ex16.29/Blob.h +++ /dev/null @@ -1,124 +0,0 @@ -/*************************************************************************** - * @file Blob.h - * @author Alan.W - * @date 02 Feb 2014 - * @remark This code is for the exercises from C++ Primer 5th Edition - * @note 03 Feb 2014 Add a constructor that takes two iterators to Blob . - * 06 Feb 2014 revise to use custome shared_ptr - ***************************************************************************/ - -#ifndef BLOB_H -#define BLOB_H -#include -#include -#include - -/** - * Blob - * manage a vector through a shared_pointer. - */ -template class Blob -{ -public: - typedef T value_type; - typedef typename std::vector::size_type size_type; - - //! constructors - Blob(); - Blob(std::initializer_list il); - - //! constructor taking two iterators - template - Blob(It b, It e); - - //! number of elements in the Blob - 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(T&& t) { data->push_back(std::move(t));} - void pop_back(); - - //! element access - T& back(); - T& operator[](size_type i); - - const T& back() const; - const T& operator [](size_type i) const; - -private: - /** - * @oldcode updated Feb 06,2014 @Alan - */ - //std::shared_ptr> data; - - shared_pointer> data; - - //! throw msg if data[i] isn't valid - void check(size_type i, const std::string &msg) const; -}; - -//! default constructor -template -Blob::Blob() : data(std::make_shared>()) -{} - -//! constructor taking initializer_list -template -Blob::Blob(std::initializer_list il): - data(std::make_shared>(il)){ } - -//! constructor taking two iterators -template //for class -template //for this member -Blob::Blob(It b, It e) : - data(std::make_shared>(b,e)) -{} - -template -void Blob::check(size_type i, const std::string &msg) const -{ - if(i >= data->size()) - throw std::out_of_range(msg); -} - -template -T& Blob::back() -{ - check(0,"back on empty Blob"); - return data->back(); -} - -template -const T& Blob::back() const -{ - check(0,"back on empty Blob"); - return data->back(); -} - - -template -T& Blob::operator [](size_type i) -{ - //! if i is too big, check function will throw,preventing access to a nonexistent element - check(i,"subscript out of range"); - return (*data)[i]; -} - - -template -const T& Blob::operator [](size_type i) const -{ - //! if i is too big, check function will throw,preventing access to a nonexistent element - check(i,"subscript out of range"); - return (*data)[i]; -} - -template -void Blob::pop_back() -{ - check(0,"pop_back on empty Blob"); - data->pop_back(); -} - -#endif // BLOB_H diff --git a/ch16/ex16.29/DebugDelete.h b/ch16/ex16.29/DebugDelete.h deleted file mode 100644 index 923dccbe..00000000 --- a/ch16/ex16.29/DebugDelete.h +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************** - * @file DebugDelete.h - * @author Alan.W - * @date 04 Feb 2014 - * @remark This code is for the exercises from C++ Primer 5th Edition - * @note - ***************************************************************************/ - -#ifndef DEBUGDELETE_H -#define DEBUGDELETE_H - -#include - -/** - * @brief The DebugDelete class is a deleter functor using delete - */ -class DebugDelete -{ -public: - DebugDelete(std::ostream& s = std::cerr) : os(s) { } - template - void operator() (T* p) const - { - os << "deleting ptr" << std::endl; - delete p; - } - -private: - std::ostream& os; -}; -#endif // DEBUGDELETE_H diff --git a/ch16/ex16.29/main.cpp b/ch16/ex16.29/main.cpp deleted file mode 100644 index 3a3387a1..00000000 --- a/ch16/ex16.29/main.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * @file main.cpp - * @author Alan.W - * @date 04 Feb 2014 - * @remark This code is for the exercises from C++ Primer 5th Edition - * @note - ***************************************************************************/ -//! -//! Exercise 16.29: -//! Revise your Blob class to use your version of shared_ptr rather than the -//! library version. -//! - - -#include -#include -#include -#include -#include "DebugDelete.h" -#include "shared_pointer.h" -#include "unique_pointer.h" -#include "Blob.h" - -int main() -{ - Blob b; - b.push_back("sss"); - - - b[0] = "zzzz"; - std::cout << b[0] << "\n"; -} - diff --git a/ch16/ex16.29/shared_pointer.h b/ch16/ex16.29/shared_pointer.h deleted file mode 100644 index d694ead4..00000000 --- a/ch16/ex16.29/shared_pointer.h +++ /dev/null @@ -1,237 +0,0 @@ -/*************************************************************************** - * @file shared_pointer.h - * @author Alan.W - * @date 04 Feb 2014 - * @remark This code is for the exercises from C++ Primer 5th Edition - * @note 06 Feb 2014 ctor taking std::shared_ptr&& added - ***************************************************************************/ -#ifndef SHARED_POINTER_H -#define SHARED_POINTER_H - -#include "DebugDelete.h" -#include -#include - -//! forward declarations needed for friendship - -template class shared_pointer; -template void swap(shared_pointer& lhs, shared_pointer& rhs); - - -/** - * @brief shared_ptr like template class - * @note don't mix this one with std::shared_ptr. - * DebugDelete is the default deleter which can be replaced at run time - */ -template -class shared_pointer -{ - friend void ::swap(shared_pointer& lhs, shared_pointer& rhs); - //! ^^^ -- don't forget this. - -public: - - //! default constructor - shared_pointer() = default; - - //! constructor taking raw pointer. - //! set the refCount as 1 - explicit shared_pointer(T* up, std::function d = DebugDelete()) : - ptr(up), refCount(new std::size_t(1)), deleter(d) { } - - //! ctor taking std::shared_ptr&& i.e. rvalue reference - explicit shared_pointer(std::shared_ptr&& sp, - std::function d = DebugDelete()); - - //! copy constructor. - //! increment useCount for each Copy - shared_pointer(const shared_pointer& sp): - ptr(sp.ptr), refCount(sp.refCount), deleter(sp.deleter) - { ++*refCount; } - - //! move constructor - shared_pointer(shared_pointer&& sp) noexcept; - - //! copy assignment - shared_pointer& operator =(const shared_pointer& rhs); - - //! move assignment - shared_pointer& operator =(shared_pointer&& rhs) noexcept; - - - //! conversion operator - operator bool() const { return ptr ? true : false;} - - //! dereference * arrow -> - T& operator* () const { return *ptr; } - T* operator->() const { return & this->operator *(); } - - //! return useCount - std::size_t use_count() const { return *refCount; } - - //! get the underlying pointer - T* get() const noexcept { return ptr; } - - //! check if the unique user - bool unique() const noexcept { return *refCount == 1;} - - //! swap member - void swap( shared_pointer& rhs) { ::swap(*this, rhs); } - - //! if unique user, free the object pointed to - void reset() noexcept { decrement_n_destroy(); } - - //! make prt point where p pointing and create a new coount for it - void reset(T* p); - - //! reset to point where p is pointing and change deleter to d. - void reset(T *p, const std::function& d) - { reset(p); deleter = d; } - - - ~shared_pointer() - { - decrement_n_destroy(); - } -private: - - T* ptr = nullptr; - std::size_t* refCount = new std::size_t(0); - - //! any functor lambda or function pointer that matched this - //! signature can replace the default one at run time. - std::function deleter{DebugDelete()}; - //! ^~~~~~~~~~~~~~^ - //! here: = doesn't work, another way is initializing it in constructor. - - //! utilities - void decrement_n_destroy(); -}; - - - -/** - * @brief swap and big 5 - */ -template -inline void -swap(shared_pointer& lhs, shared_pointer& rhs) -{ - using std::swap; - swap(lhs.ptr, rhs.ptr); - swap(lhs.refCount, rhs.refCount); - swap(lhs.deleter, rhs.deleter); -} - - -/** - * @brief ctor taking std::shared_ptr&& i.e. rvalue reference - * an interface between shared_pointer and std::shared_ptr. - * only rvalue AND unique ownership can use this ctor. - */ -template -inline -shared_pointer::shared_pointer(std::shared_ptr&& sp, - std::function d) -{ - if(sp.unique()) - *this = shared_pointer(new T(*sp), d); - else - throw std::runtime_error - ("only unique and rvalue reference can transfer ownership--@Alan\n"); -} - - -//! move constructor -template -inline -shared_pointer::shared_pointer(shared_pointer&& sp) noexcept: - ptr(sp.ptr), refCount(sp.refCount), deleter(std::move(sp.deleter)) -{ - sp.ptr = nullptr; - sp.refCount = nullptr; -} - - -//! copy assignment -template -inline shared_pointer& -shared_pointer::operator =(const shared_pointer& rhs) -{ - //! increment rhs.refCount first to ensure safty when self-assignment - ++*rhs.refCount; - - //! for lhs: - decrement_n_destroy(); - - //! copy datastructure from rhs to this. - ptr = rhs.ptr; - refCount = rhs.refCount; - deleter = rhs.deleter; - - return *this; -} - - -//! move assignment -template -inline shared_pointer& -shared_pointer::operator =(shared_pointer&& rhs) noexcept -{ - //! for lhs - decrement_n_destroy(); - - //! swap two sides - ::swap(*this, rhs); - - std::cout << "shared_pointer::move=\n"; - - return *this; -} - - -//! make prt point where p pointing and create a new coount for it -template -inline void -shared_pointer::reset(T* p) -{ - if(ptr != p) - { - decrement_n_destroy(); - ptr = p; - refCount = new std::size_t(1); - } -} - - -/** - *@brief operators: << - **/ - -template -inline std::ostream& -operator <<(std::ostream& os, shared_pointer p) -{ - os << p.get(); - return os; -} - - -//! utilities for decrement and delete using deleter. -template -inline void -shared_pointer::decrement_n_destroy() -{ - if(ptr) - { - if (--*refCount == 0) - { - delete refCount; - deleter(ptr); - } - refCount = nullptr; - ptr = nullptr; - } -} - -#endif // SHARED_POINTER_H diff --git a/ch16/ex16.29/unique_pointer.h b/ch16/ex16.29/unique_pointer.h deleted file mode 100644 index 8a49e2c7..00000000 --- a/ch16/ex16.29/unique_pointer.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef UNIQUE_POINTER_H -#define UNIQUE_POINTER_H - -#include - -//! forward declarations for friendship - -template class unique_pointer; -template void - swap(unique_pointer& lhs, unique_pointer& rhs); - -/** - * @brief std::unique_ptr like class template. - */ -template -class unique_pointer -{ - friend void swap(unique_pointer& lhs, unique_pointer& rhs); - -public: - //! preventing copy and assignment - unique_pointer(const unique_pointer&) = delete; - unique_pointer& operator = (const unique_pointer&) = delete; - - //! default constructor and one taking T* - unique_pointer() = default; - explicit unique_pointer(T* up): ptr(up) { } - - //! move constructor - unique_pointer(unique_pointer&& up) noexcept - : ptr(up.ptr) { up.ptr = nullptr; } - - //! move assignment - unique_pointer& operator =(unique_pointer&& rhs) noexcept; - - //! std::nullptr_t assignment - unique_pointer& operator =(std::nullptr_t n) noexcept; - - - - //! operator overloaded : * -> bool - T& operator *() const { return *ptr; } - T* operator ->() const { return & this->operator *(); } - operator bool() const { return ptr ? true : false; } - - //! return the underlying pointer - T* get() const noexcept { return ptr;} - - //! swap member using swap friend - void swap(unique_pointer &rhs) {::swap(*this, rhs);} - - //! free and make it point to nullptr or to p's pointee. - void reset() noexcept { deleter(ptr); ptr = nullptr; } - void reset(T* p) noexcept { deleter(ptr); ptr = p; } - - //! return ptr and make ptr point to nullptr. - T* release(); - - - ~unique_pointer() - { - deleter(ptr); - } -private: - T* ptr = nullptr; - D deleter = D(); -}; - - -//! swap -template -inline void -swap(unique_pointer& lhs, unique_pointer& rhs) -{ - using std::swap; - swap(lhs.ptr, rhs.ptr); - swap(lhs.deleter, rhs.deleter); -} - -//! move assignment -template -inline unique_pointer& -unique_pointer::operator =(unique_pointer&& rhs) noexcept -{ - //! prevent self-assignment - if(this->ptr != rhs.ptr) - { - deleter(ptr); - ptr = nullptr; - ::swap(*this, rhs); - } - return *this; -} - - -//! std::nullptr_t assignment -template -inline unique_pointer& -unique_pointer::operator =(std::nullptr_t n) noexcept -{ - if(n == nullptr) - { - deleter(ptr); ptr = nullptr; - } - return *this; -} - - //! relinquish contrul by returnning ptr and making ptr point to nullptr. -template -inline T* -unique_pointer::release() -{ - T* ret = ptr; - ptr = nullptr; - return ret; -} -#endif // UNIQUE_POINTER_H diff --git a/ch16/ex16_29_blob.h b/ch16/ex16_29_blob.h new file mode 100644 index 00000000..024332ee --- /dev/null +++ b/ch16/ex16_29_blob.h @@ -0,0 +1,446 @@ +#ifndef CP5_EX16_24_BLOB_H_ +#define CP5_EX16_24_BLOB_H_ + +#include +using std::vector; + +#include +using std::initializer_list; + +#include "ex16_28_shared_ptr.h" +#include +#include + +template class BlobPtr; +template class ConstBlobPtr; +template class Blob; + +//============================================================================== +// Blob - custom vector. +//============================================================================== + +template class Blob { + friend class ConstBlobPtr; + friend class BlobPtr; + friend bool operator==(const Blob& lhs, const Blob& rhs) { return *lhs.data == *rhs.data; } + friend bool operator!=(const Blob& lhs, const Blob& rhs) { return !(lhs == rhs); } + friend bool operator<(const Blob& lhs, const Blob& rhs) + { + return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), + rhs.data->end()); + } + friend bool operator>(const Blob& lhs, const Blob& rhs) { return rhs < lhs; } + friend bool operator<=(const Blob& lhs, const Blob& rhs) { return !(rhs < lhs); } + friend bool operator>=(const Blob& lhs, const Blob& rhs) { return !(lhs < rhs); } + +public: + using size_type = typename vector::size_type; + + Blob() : data(new vector()) {} + Blob(initializer_list il) : data(new vector(il)) {} + template Blob(It b, It e) : data(new vector(b, e)) {} + + Blob(const Blob& b) : data(new vector(*b.data)) {} + Blob& operator=(const Blob& b); + + Blob(Blob&& b) NOEXCEPT : data(std::move(b.data)) {} + Blob& operator=(Blob&& b) NOEXCEPT; + + BlobPtr begin(); + BlobPtr end(); + + ConstBlobPtr cbegin() const; + ConstBlobPtr cend() const; + + T& operator[](size_t n); + const T& operator[](size_t n) const; + + 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(T&& s) { data->push_back(std::move(s)); } + + void pop_back(); + T& front(); + T& back(); + const T& front() const; + const T& back() const; + +private: + void check(size_type, const T&) const; + + SharedPtr> data; +}; + +//------------------------------------------------------------------------------ +// member function. +//------------------------------------------------------------------------------ + +template Blob& Blob::operator=(const Blob& b) +{ + data = new vector(*b.data); + return *this; +} + +template Blob& Blob::operator=(Blob&& b) NOEXCEPT +{ + if (this != &b) { + data = std::move(b.data); + b.data = nullptr; + } + + return *this; +} + +template BlobPtr Blob::begin() +{ + return BlobPtr(*this); +} + +template BlobPtr Blob::end() +{ + return BlobPtr(*this, data->size()); +} + +template ConstBlobPtr Blob::cbegin() const +{ + return ConstBlobPtr(*this); +} + +template ConstBlobPtr Blob::cend() const +{ + return ConstBlobPtr(*this, data->size()); +} + +template inline void Blob::pop_back() +{ + check(0, "pop_back on empty Blob"); + data->pop_back(); +} + +template inline T& Blob::front() +{ + check(0, "front on empty Blob"); + return data->front(); +} + +template inline T& Blob::back() +{ + check(0, "back on empty Blob"); + return data->back(); +} + +template inline const T& Blob::front() const +{ + check(0, "front on empty Blob"); + return data->front(); +} + +template inline const T& Blob::back() const +{ + check(0, "back on empty Blob"); + return data->back(); +} + +template inline void Blob::check(size_type i, const T& msg) const +{ + if (i >= data->size()) throw std::out_of_range(msg); +} + +template inline T& Blob::operator[](size_t n) +{ + check(n, "out of range"); + return data->at(n); +} + +template inline const T& Blob::operator[](size_t n) const +{ + check(n, "out of range"); + return data->at(n); +} + +//================================================================================= +// BlobPtr - custom iterator of Blob +//================================================================================= + +template class BlobPtr { + friend bool operator==(const BlobPtr& lhs, const BlobPtr& rhs) + { + return lhs.curr == rhs.curr; + } + friend bool operator!=(const BlobPtr& lhs, const BlobPtr& rhs) { return !(lhs == rhs); } + friend bool operator<(const BlobPtr& lhs, const BlobPtr& rhs) + { + return lhs.curr < rhs.curr; + } + friend bool operator>(const BlobPtr& lhs, const BlobPtr& rhs) + { + return lhs.curr > rhs.curr; + } + friend bool operator<=(const BlobPtr& lhs, const BlobPtr& rhs) + { + return lhs.curr <= rhs.curr; + } + friend bool operator>=(const BlobPtr& lhs, const BlobPtr& rhs) + { + return lhs.curr >= rhs.curr; + } + +public: + BlobPtr() : curr(0) {} + BlobPtr(Blob& s, size_t sz = 0) : wptr(s.data), curr(sz) {} + + T& operator*() const; + T* operator->() const; + BlobPtr& operator++(); + BlobPtr& operator--(); + BlobPtr operator++(int); + BlobPtr operator--(int); + BlobPtr& operator+=(size_t); + BlobPtr& operator-=(size_t); + BlobPtr operator+(size_t) const; + BlobPtr operator-(size_t) const; + + T& operator[](size_t n); + const T& operator[](size_t n) const; + +private: + SharedPtr> check(size_t, const T&) const; + + std::weak_ptr> wptr; + size_t curr; +}; + +//------------------------------------------------------------------------------ +// member function. +//------------------------------------------------------------------------------ + +template T& BlobPtr::operator*() const +{ + auto p = check(curr, "dereference past end"); + return (*p)[curr]; +} + +template T* BlobPtr::operator->() const +{ + return &this->operator*(); +} + +template inline BlobPtr& BlobPtr::operator++() +{ + check(curr, "increment past end of BlobPtr"); + ++curr; + return *this; +} + +template inline BlobPtr& BlobPtr::operator--() +{ + --curr; + check(-1, "decrement past begin of BlobPtr"); + return *this; +} + +template inline BlobPtr BlobPtr::operator++(int) +{ + BlobPtr ret = *this; + ++*this; + return ret; +} + +template inline BlobPtr BlobPtr::operator--(int) +{ + BlobPtr ret = *this; + --*this; + return ret; +} + +template inline BlobPtr& BlobPtr::operator+=(size_t n) +{ + curr += n; + check(curr, "increment past end of BlobPtr"); + return *this; +} + +template inline BlobPtr& BlobPtr::operator-=(size_t n) +{ + curr -= n; + check(curr, "increment past end of BlobPtr"); + return *this; +} + +template inline BlobPtr BlobPtr::operator+(size_t n) const +{ + BlobPtr ret = *this; + ret += n; + return ret; +} + +template inline BlobPtr BlobPtr::operator-(size_t n) const +{ + BlobPtr ret = *this; + ret -= n; + return ret; +} + +template inline SharedPtr> BlobPtr::check(size_t i, const T& msg) const +{ + auto ret = wptr.lock(); + if (!ret) throw std::runtime_error("unbound BlobPtr"); + if (i >= ret->size()) throw std::out_of_range(msg); + return ret; +} + +template inline T& BlobPtr::operator[](size_t n) +{ + auto p = check(n, "dereference out of range."); + return (*p)[n]; +} + +template inline const T& BlobPtr::operator[](size_t n) const +{ + auto p = check(n, "dereference out of range."); + return (*p)[n]; +} + +//================================================================================= +// ConstBlobPtr - custom const_iterator of Blob +//================================================================================= + +template class ConstBlobPtr { + friend bool operator==(const ConstBlobPtr& lhs, const ConstBlobPtr& rhs) + { + return lhs.curr == rhs.curr; + } + friend bool operator!=(const ConstBlobPtr& lhs, const ConstBlobPtr& rhs) + { + return !(lhs == rhs); + } + friend bool operator<(const ConstBlobPtr& lhs, const ConstBlobPtr& rhs) + { + return lhs.curr < rhs.curr; + } + friend bool operator>(const ConstBlobPtr& lhs, const ConstBlobPtr& rhs) + { + return lhs.curr > rhs.curr; + } + friend bool operator<=(const ConstBlobPtr& lhs, const ConstBlobPtr& rhs) + { + return lhs.curr <= rhs.curr; + } + friend bool operator>=(const ConstBlobPtr& lhs, const ConstBlobPtr& rhs) + { + return lhs.curr >= rhs.curr; + } + +public: + ConstBlobPtr() : curr(0) {} + ConstBlobPtr(const Blob& s, size_t sz = 0) : wptr(s.data), curr(sz) {} + + const T& operator*() const; + const T* operator->() const; + ConstBlobPtr& operator++(); + ConstBlobPtr& operator--(); + ConstBlobPtr operator++(int); + ConstBlobPtr operator--(int); + ConstBlobPtr& operator+=(size_t); + ConstBlobPtr& operator-=(size_t); + ConstBlobPtr operator+(size_t) const; + ConstBlobPtr operator-(size_t) const; + + const T& operator[](size_t n) const; + +private: + std::SharedPtr> check(size_t, const T&) const; + + std::weak_ptr> wptr; + size_t curr; +}; + +//------------------------------------------------------------------------------ +// member function. +//------------------------------------------------------------------------------ + +template inline const T& ConstBlobPtr::operator*() const +{ + auto p = check(curr, "dereference past end"); + return (*p)[curr]; +} + +template inline const T* ConstBlobPtr::operator->() const +{ + return &this->operator*(); +} + +template inline ConstBlobPtr& ConstBlobPtr::operator++() +{ + check(curr, "increment past end of ConstBlobPtr"); + ++curr; + return *this; +} + +template inline ConstBlobPtr& ConstBlobPtr::operator--() +{ + --curr; + check(-1, "decrement past begin of ConstBlobPtr"); + return *this; +} + +template inline ConstBlobPtr ConstBlobPtr::operator++(int) +{ + ConstBlobPtr ret = *this; + ++*this; + return ret; +} + +template inline ConstBlobPtr ConstBlobPtr::operator--(int) +{ + ConstBlobPtr ret = *this; + --*this; + return ret; +} + +template inline ConstBlobPtr& ConstBlobPtr::operator+=(size_t n) +{ + curr += n; + check(curr, "increment past end of ConstBlobPtr"); + return *this; +} + +template inline ConstBlobPtr& ConstBlobPtr::operator-=(size_t n) +{ + curr -= n; + check(curr, "increment past end of ConstBlobPtr"); + return *this; +} + +template inline ConstBlobPtr ConstBlobPtr::operator+(size_t n) const +{ + ConstBlobPtr ret = *this; + ret += n; + return ret; +} + +template inline ConstBlobPtr ConstBlobPtr::operator-(size_t n) const +{ + ConstBlobPtr ret = *this; + ret -= n; + return ret; +} + +template +inline std::SharedPtr> ConstBlobPtr::check(size_t i, const T& msg) const +{ + auto ret = wptr.lock(); + if (!ret) throw std::runtime_error("unbound BlobPtr"); + if (i >= ret->size()) throw std::out_of_range(msg); + return ret; +} + +template inline const T& ConstBlobPtr::operator[](size_t n) const +{ + auto p = check(n, "dereference out of range."); + return (*p)[n]; +} + +#endif // CP5_EX16_24_BLOB_H_ diff --git a/ch16/ex16_29_blob_test.cpp b/ch16/ex16_29_blob_test.cpp new file mode 100644 index 00000000..737ab482 --- /dev/null +++ b/ch16/ex16_29_blob_test.cpp @@ -0,0 +1,29 @@ +#include "ex16_24_blob.h" +#include +#include + +int main() +{ + Blob sb1{"a", "b", "c"}; + Blob sb2 = sb1; + + sb2[2] = "b"; + + if (sb1 > sb2) { + for (auto iter = sb2.cbegin(); iter != sb2.cend(); ++iter) { + std::cout << *iter << " "; + } + std::cout << std::endl; + } + + ConstBlobPtr iter(sb2); + std::cout << iter->size() << std::endl; + + std::vector vec{"good", "for", "you"}; + Blob sb3(vec.begin(), vec.end()); + + for (auto&& s : sb3) { + std::cout << s << " "; + } + std::cout << "\n"; +}