14-1
Implement the comparison operation that operates on Ptr.
bool compare_Core_handles(const Handle<Core>& lhs,const Handle<Core>& rhs)
{
return compare(*lhs,*rhs);
}
14-4
Reimplement the Str class to use the final version of Ptr.
//"Ptr.h"
#ifndef Ptr_H
#define Ptr_H
template <class T> class Ptr {
public:
Ptr() : refptr(new size_t(1)), p(0) { }
Ptr(T* t) : refptr(new size_t(1)), p(t) { }
Ptr(const Ptr& h) : refptr(h.refptr), p(h.p)
{
++*refptr;
}
void make_unique();
Ptr& operator=(const Ptr&);
~Ptr();
operator bool() const
{
return p;
}
T& operator*() const
{
if (p)
return *p;
throw std::runtime_error("unbound Ptr");
}
T* operator->() const {
if (p)
return p;
throw std::runtime_error("unbound Ptr");
}
private:
T* p;
size_t* refptr;
};
template<class T> void Ptr<T>::make_unique()
{
if (*refptr != 1)
{
--*refptr;
refptr = new size_t(1);
p = p ? clone(p) : 0;
}
}
template<class T> T* clone(const T* vp)
{
return new T(*vp);
}
template<class T> Ptr<T>& Ptr<T>::operator=(const Ptr& rhs)
{
++*rhs.refptr;
// free the left-hand side, destroying pointers if appropriate
if (--*refptr == 0) {
delete refptr;
delete p;
}
// copy in values from the right-hand side
refptr = rhs.refptr;
p = rhs.p;
return *this;
}
template<class T> Ptr<T>::~Ptr()
{
if (--*refptr == 0) {
delete refptr;
delete p;
}
}
#endif// Ptr_H
//"Str.h"
#ifndef Str_H
#define Str_H
#include <iostream>
#include <iterator>
#include "Vec.h"
#include "Ptr.h"
#include <string.h>
#include <iterator>
class Str
{
friend std::istream& operator>> (std::istream&, Str&);
friend Str operator+ (const Str&, const char*);
friend Str operator+ (const char*, const Str&);
public:
typedef Vec<char>::size_type size_type;
typedef char* iterator;
typedef const char* const_iterator;
Str() : data(new Vec<char>) { }
Str(size_type n, char c) : data(new Vec<char>(n, c)) { }
Str(const char* cp) : data(new Vec<char>)
{
std::copy(cp, cp + std::strlen(cp), std::back_inserter(*data));
}
template <class In> Str(In b, In e) : data(new Vec<char>)
{
std::copy(b, e, std::back_inserter(*data));
}
size_type size() const
{
return data->size();
}
iterator begin()
{
data.make_unique();
return data->begin();
}
const_iterator begin() const
{
return data->begin();
}
iterator end()
{
data.make_unique();
return data->end();
}
const_iterator end() const
{
return (*data).end();
}
Str& operator+= (const Str& s);
char& operator[](size_type i)
{
data.make_unique();
return (*data)[i];
}
const char& operator[](size_type i) const
{
return (*data)[i];
}
operator void*() const
{
return data->empty() ? 0 : (void*)1;
}
std::istream& getline(std::istream& is)
{
data.make_unique();
data->clear();
char c;
while (is.get(c) && isspace(c));
if (is)
{
do
{
(*data).push_back(c);
} while (is.get(c) && c != '\n');
if (is)
is.unget();
}
return is;
}
template <class In> void insert(iterator iter, In b, In e)
{
data.make_unique();
data->insert(iter, b, e);
}
private:
Ptr< Vec<char> > data;
};
std::istream& operator>> (std::istream& is, Str& s)
{
s.data.make_unique();
s.data->clear();
char c;
while (is.get(c) && isspace(c));
if (is)
{
do
{
s.data->push_back(c);
} while (is.get(c) && !isspace(c));
if (is)
is.unget();
}
return is;
}
std::ostream& operator<< (std::ostream& os, const Str& s)
{
//for (Str::size_type i = 0; i != s.size(); ++i)
//{
// os << s[i];
//}
std::ostream_iterator<char> iter(os);
for (Str::size_type i = 0; i != s.size(); i++)
{
*iter++ = s[i];
}
return os;
}
Str& Str::operator+= (const Str& s)
{
data.make_unique();
std::copy(s.data->begin(), s.data->end(), std::back_inserter(*data));
return *this;
}
Str operator+ (const Str& x, const Str& y)
{
Str temp;
temp = x;
temp += y;
return temp;
}
Str operator+ (const Str& x, const char* y)
{
Str temp;
temp = x;
std::copy(y, y + std::strlen(y), std::back_inserter(*temp.data));
return temp;
}
Str operator+ (const char* x, const Str& y)
{
Str temp;
std::copy(x, x + std::strlen(x), std::back_inserter(*temp.data));
temp += y;
return temp;
}
bool operator< (const Str& x, const Str& y)
{
Str::size_type i = 0;
while (i != x.size() && i != y.size())
{
if (x[i] == y[i]) ++i;
else return x[i] < y[i] ? true : false;
}
if (!x[i]) return true;
else return false;
}
bool operator> (const Str& x, const Str& y)
{
Str::size_type i = 0;
while (i != x.size() && i != y.size())
{
if (x[i] == y[i]) ++i;
else return x[i] > y[i] ? true : false;
}
if (!y[i]) return true;
else return false;
}
bool operator== (const Str& x, const Str& y)
{
Str::size_type i = 0;
while (i != x.size() && i != y.size())
{
if (x[i] == y[i]) ++i;
else return false;
}
if (!x[i] && !y[i]) return true;
else return false;
}
bool operator!= (const Str& x, const Str& y)
{
return !(x == y);
}
#endif // Str_H
//"Vec.h"
#ifndef Vec_H
#define Vec_H
#include <memory>
#include <cstddef>
#include <algorithm>
template <class T>
class Vec
{
public:
typedef T* iterator;
typedef const T* const_iterator;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef T value_type;
Vec()
{
create();
}
explicit Vec(size_type n, const T& t = T())
{
create(n, t);
}
Vec(const Vec& v)
{
create(v.begin(), v.end());
}
template <class In> Vec(In b, In e)
{
create();
std::copy(b, e, std::back_inserter(*this));
}
Vec& operator=(const Vec&);
~Vec()
{
uncreate();
}
T& operator[](size_type i)
{
return data[i];
}
const T& operator[](size_type i) const
{
return data[i];
}
void push_back(const T& t)
{
if (avail == limit)
grow();
unchecked_append(t);
}
template <class In> void insert(iterator iter, In b, In e)
{
size_type new_size = (limit - data) + (e - b);
iterator new_data = alloc.allocate(new_size);
iterator temp1 = std::uninitialized_copy(data, iter, new_data);
iterator temp2 = std::uninitialized_copy(b, e, temp1);
iterator new_avail = std::uninitialized_copy(iter, avail, temp2);
uncreate();
data = new_data;
avail = new_avail;
limit = data + new_size;
}
template <class In> void assign(In array[])
{
In *array_end = array;
while (*array_end) array_end++;
size_type new_size = array_end - array;
iterator new_data = alloc.allocate(new_size);
iterator new_avail = std::uninitialized_copy(array, array_end, new_data);
uncreate();
data = new_data;
avail = new_avail;
limit = data + new_size;
}
size_type size() const
{
return avail - data;
}
iterator begin()
{
return data;
}
const_iterator begin() const
{
return data;
}
iterator end()
{
return avail;
}
const_iterator end() const
{
return avail;
}
void clear()
{
uncreate();
}
iterator erase(iterator it)
{
for (iterator i = it; i != avail; ++i)
{
alloc.destroy(i);
if ((i + 1) != avail) alloc.construct(i, *(i + 1));
}
--avail;
return it;
}
bool empty() const
{
return data == avail;
}
private:
iterator data;
iterator avail;
iterator limit;
std::allocator<T> alloc;
void create();
void create(size_type, const T&);
void create(const_iterator, const_iterator);
void uncreate();
void grow();
void unchecked_append(const T&);
};
template <class T>
Vec<T>& Vec<T>::operator=(const Vec& rhs)
{
if (&rhs != this)
{
uncreate();
create(rhs.begin(), rhs.end());
}
return *this;
}
template <class T>
void Vec<T>::create()
{
data = avail = limit = 0;
}
template <class T>
void Vec<T>::create(size_type n, const T& val)
{
data = alloc.allocate(n);
limit = avail = data + n;
std::uninitialized_fill(data, limit, val);
}
template <class T>
void Vec<T>::create(const_iterator i, const_iterator j)
{
data = alloc.allocate(j - i);
limit = avail = std::uninitialized_copy(i, j, data);
}
template <class T>
void Vec<T>::uncreate()
{
if (data)
{
iterator it = avail;
while (it != data)
alloc.destroy(--it);
alloc.deallocate(data, limit - data);
}
data = limit = avail = 0;
}
template <class T>
void Vec<T>::grow()
{
size_type new_size = std::max(2 * (limit - data), ptrdiff_t(1));
iterator new_data = alloc.allocate(new_size);
iterator new_avail = std::uninitialized_copy(data, avail, new_data);
uncreate();
data = new_data;
avail = new_avail;
limit = data + new_size;
}
template <class T>
void Vec<T>::unchecked_append(const T& val)
{
alloc.construct(avail++, val);
}
#endif // Vec_H
//"main.h"
#define _SCL_SECURE_NO_WARNINGS
#include "Str.h"
#include <string>
using namespace std;
int main()
{
Str s1("abc"), s2;
string str = "hello~";
Vec<char> v1(str.begin(), str.end());
for (Vec<char>::size_type i = 0; i != v1.size(); i++)
{
cout << v1[i];
}
cout << endl;
cout << s1.size() << endl << s2.size() << endl;
if (s1){ cout << "s1 exist" << endl; }
else { cout << "s1 null" << endl; }
if (s2){ cout << "s2 exist" << endl; }
else { cout << "s2 null" << endl; }
s2.getline(cin);
if (s1 < s2)
{
cout << "<" << endl;
}
else if (s1 == s2)
{
cout << "==" << endl;
}
else
{
cout << ">" << endl;
}
cout << s1 << endl << s2 << endl;
cout << s1.size() << endl << s2.size() << endl;
cout << "test insert:" << endl;
s2.insert(s2.begin() + 1, s1.begin(), s1.end());
cout << s2 << endl;
cout << "test assign:" << endl;
v1.assign("v1 is assigned");
for (Vec<char>::size_type i = 0; i != v1.size(); i++)
{
cout << v1[i];
}
cout << endl;
system("pause");
}